获取System.Type的默认构造函数(即没有参数的实例构造函数)的最有效方法是什么?
我在想下面的代码,但似乎应该有一种更简单、更有效的方法。
Type type = typeof(FooBar)
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
type.GetConstructors(flags)
.Where(constructor => constructor.GetParameters().Length == 0)
.First();
type.GetConstructor(Type.EmptyTypes)
如果你真的需要 ConstructorInfo 对象,那么看看 Curt Hagenlocher 的答案。
另一方面,如果你真的只是想在运行时从System.Type
创建一个对象,请参阅System.Activator.CreateInstance
- 它不仅仅是面向未来的(Activator处理的细节比ConstructorInfo.Invoke
),它也不那么丑陋。
如果你有泛型类型参数,那么 Jeff Bridgman 的答案是最好的。如果你只有一个 Type 对象来表示你想要构造的类型,你可以像 Alex Lyman 建议的那样使用Activator.CreateInstance(Type)
,但我被告知它很慢(虽然我没有亲自分析它)。
但是,如果您发现自己非常频繁地构造这些对象,则可以使用动态编译的 Linq 表达式使用更雄辩的方法:
using System;
using System.Linq.Expressions;
public static class TypeHelper
{
public static Func<object> CreateDefaultConstructor(Type type)
{
NewExpression newExp = Expression.New(type);
// Create a new lambda expression with the NewExpression as the body.
var lambda = Expression.Lambda<Func<object>>(newExp);
// Compile our new lambda expression.
return lambda.Compile();
}
}
只需致电返回给您的代表即可。 您应该缓存此委托,因为不断重新编译 Linq 表达式的成本可能很高,但如果每次都缓存委托并重用它,它会非常快! 我个人使用按类型索引的静态查找字典。 当您处理可能只知道 Type 信息的序列化对象时,此函数会派上用场。
注意:如果类型不可构造或没有默认构造函数,则此操作可能会失败!
如果只想获取默认构造函数来实例化类,并且要获取该类型作为函数的泛型类型参数,则可以执行以下操作:
T NewItUp<T>() where T : new()
{
return new T();
}
您可能想尝试FormatterServices.GetUninitializedObject(Type)这个比Activator.CreateInstance更好
但是,此方法不调用对象构造函数,所以如果你在那里设置初始值,这将不起作用检查 MSDN 是否有这个东西http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject.aspx
这里还有另一种方式http://www.ozcandegirmenci.com/post/2008/02/Create-object-instances-Faster-than-Reflection.aspx
但是,如果对象具有参数化构造函数,则此对象将失败
希望这有帮助