我有一个方法,它将构造函数参数作为
Expression<func<T>>
因此声明为
object[] _constructorArgs = () => new MyClass("StringParam", 56, "ThirdParam");
我会将此对象实例化为;
Activator.CreateInstance(typeof(MyClass), _constructorArgs);
哪种方法很好,但速度有点慢。
有没有办法可以根据_constructorArgs的内容收集类型构造函数,这样我就可以调用
ConstructorInfo.Invoke(_constructorArgs);
我知道Invoke是可行的,它只是根据_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);
}
但是,如果我改为做以下事情;
ConstructorInfo c = type.GetConstructors().FirstOrDefault();
//Get the types constructor
return c.Invoke(_args);
我获得了更好的性能,我说的是第一次在一百万次迭代中花费大约2800毫秒,使用Invoke将其降低到大约1000毫秒,因此速度提高了2.8倍。
如果第一个构造函数总是与给定的参数匹配,这将很有用,但这不会总是如此。
我想知道如何根据给定的参数获取正确的ConstructorInfo。
答案 0 :(得分:1)
Activator.CreateInstance()
调用GetConstructors()
并迭代它们以找到匹配的。这可以解释性能上的差异 - 如果你推出自己的实现机会,你最终会得到相同或更差的性能。
您可以通过使用parameterType.IsAssignableFrom(argType)
比较类型来简化流程,并返回第一个匹配项 - 您最终可能会使用与Activator.CreateInstance()
不同的构造函数,因为它使用最佳匹配,而不是第一场比赛:
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());
答案 1 :(得分:1)
如果每秒有一百万个新物体对你来说不够快,那么你将不得不走得更远。你需要开始缓存。缓存最简单的事情是构造函数本身,因此您不必一直搜索正确的构造函数。然而...
你为什么要这样做?你为什么不直接打电话给lambda?您已经获得了实例化该类的所有代码,然后将其丢弃并使用Activator.CreateInstance
?为什么?即使您这样做,也不需要搜索以获取构造函数 - NewExpression.Constructor
具有您需要的ConstructorInfo
。只是做
((NewExpression)constructor.Body).Constructor.Invoke(_args)
你完成了,不需要搜索。所有元数据都已存在于表达式树中。
请解释为什么你不能简单地return constructor();
(如果可能/需要缓存) - 将事物作为lambda参数传递是很方便的,因为你可以轻松地缓存方法本身)
答案 2 :(得分:0)
可能会有点迟,但我发现了一个很好的缓存实现,声称比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
完整的实施可以在这里找到: http://www.cyberforum.ru/blogs/32756/blog2078.html