C# 获取与参数匹配的构造函数

C# 获取与参数匹配的构造函数,c#,.net,reflection,activator,C#,.net,Reflection,Activator,我有一个方法,它将构造函数参数作为 Expression<func<T>> 我将这个对象实例化为 Activator.CreateInstance(typeof(MyClass), _constructorArgs); 这很好,但有点慢 有没有一种方法可以根据_constructorArgs的内容收集类型构造函数,以便调用 ConstructorInfo.Invoke(_constructorArgs); ? 我知道这样调用是可能的,它只是基于_constructo

我有一个方法,它将构造函数参数作为

Expression<func<T>>
我将这个对象实例化为

Activator.CreateInstance(typeof(MyClass), _constructorArgs);
这很好,但有点慢

有没有一种方法可以根据_constructorArgs的内容收集类型构造函数,以便调用

ConstructorInfo.Invoke(_constructorArgs);
?

我知道这样调用是可能的,它只是基于_constructorArgs中的参数找到正确的构造函数

编辑-为清晰起见

抱歉,当我第一次问这个问题的时候,我很累,应该多考虑一下

我现在做的是:

    public object Create<T>(Expression<Func<T>> constructor)
    {
        //I didn't include this step in the original code
        var constructorArguments =
            (((NewExpression)constructor.Body).Arguments.Select(
                argument => Expression.Lambda(argument).Compile().DynamicInvoke())).ToArray();

        object[] _args = constructorArguments;

        return Activator.CreateInstance(typeof(T), _args);
    }
我得到了更好的性能,我说的是第一次迭代在一百万次迭代中花费了2800毫秒,使用Invoke将其降低到1000毫秒左右,因此速度提高了2.8倍

如果第一个构造函数总是匹配给定的参数,这将非常有效,但情况并非总是如此


我想知道如何根据给定的参数获取正确的构造函数信息。

Activator.CreateInstance()
under-the-hood调用
GetConstructors()
,并对其进行迭代以找到匹配的构造函数。这就解释了性能上的差异——如果您使用自己的实现,很可能最终会得到相同或更差的性能

您可以通过使用
parameterType.IsAssignableFrom(argType)
比较类型来简化此过程,并返回第一个匹配-您可能最终使用的构造函数不同于
Activator.CreateInstance()
,因为它使用的是最佳匹配,而不是第一个匹配:


如果每秒一百万个新对象的速度对你来说不够快,你将不得不更深入。你需要开始缓存东西。缓存最简单的东西是构造函数本身,这样您就不必一直搜索正确的构造函数。然而

你为什么这么做?你为什么不干脆直接给lambda打个电话?您已经拥有了实例化该类的所有代码,然后将其丢弃并使用
Activator.CreateInstance
?为什么?即使这样做,也不需要搜索构造函数-
NewExpression。构造函数
具有所需的
ConstructorInfo
。照办

((NewExpression)constructor.Body).Constructor.Invoke(_args) 
你完成了,不需要搜索。所有元数据都已存在于表达式树中


请解释为什么不能简单地执行
返回构造函数()(如果可能/需要,可以使用缓存-可以方便地将内容作为lambda参数传递,因为您可以轻松地缓存方法本身)。

可能有点晚,但我发现了一个很好的缓存实现,它声称比t Activator.CreateInstance快70倍

this.Item = (T)Activator.CreateInstance(typeof(T), new Object[] { x, y }, null); // Classical approach
this.Item = Constructor<Func<int,int,T>>.Ctor(x,y); // Dynamic constructor approach
this.Item=(T)Activator.CreateInstance(typeof(T),新对象[]{x,y},null);//经典方法
this.Item=Constructor.Ctor(x,y);//动态构造函数方法
完整的实现可在此处找到:

您的问题不清楚。也许你应该提供一个完整的例子?第二个代码块实际上无法编译,您不能将lambda(a
Func
)分配给
object[]
类型的变量。此外,您应该澄清“慢”部分
Activator.CreateInstance
在正常使用中不应该那么慢,而且
ConstructorInfo.Invoke
也不会快很多。你想取得什么样的成绩?你确定不是你的构造函数代码慢吗?Jods,谢谢你的回复。我忘了把Lamda的复杂性包括在内,现在我把它和更清晰的内容放在了原来的帖子里。测试时间在两个方面都是针对同一个构造函数的,因此在本例中,构造函数不是问题所在。如果有比ConstructorInfo.Invoke(_args)更快的方法,那么我也很乐意看看。我已经编辑了您的标题。请参见“”,其中的共识是“不,他们不应该”。
DynamicInvoke
非常慢……当校准构造函数()时,我得到“是一个变量,但像方法一样使用”。然而,将它从Expression更改为Func可以让我做到这一点,并提供了显著的性能提升。我正在探索可用于调用成员的选项,这就是为什么我对性能如此好奇的原因。你(直接或间接)让我看到了一些选择。谢谢@每个极客直接使用委托(在本例中是
Func
)是最快的选择之一。唯一可能稍微快一点的是使用接口;但这通常是不值得的-差别很小,处理委托非常简单:)是的,你是对的,如果你使用
表达式
,你首先要做
编译
,这在您的情况下会适得其反-将表达式树更改为简单委托可以让编译器在编译时而不是运行时准备所有内容(当然,有JIT编译,但是:)
class DerivedClass : BaseClass { }

class Test
{
    public Test(BaseClass c)
    {
    }

    public Test(DerivedClass c)
    {
    }
}

// Uses the most specific constructor, Test(DerivedClass):
Activator.CreateInstance(typeof(Test), new DerivedClass());
((NewExpression)constructor.Body).Constructor.Invoke(_args) 
this.Item = (T)Activator.CreateInstance(typeof(T), new Object[] { x, y }, null); // Classical approach
this.Item = Constructor<Func<int,int,T>>.Ctor(x,y); // Dynamic constructor approach