获取System.Type的默认构造函数(即没有参数的实例构造函数)的最有效方法是什么?
我正在考虑下面的代码,但似乎应该有一种更简单,更有效的方法。
Type type = typeof(FooBar)
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
type.GetConstructors(flags)
.Where(constructor => constructor.GetParameters().Length == 0)
.First();
答案 0 :(得分:124)
type.GetConstructor(Type.EmptyTypes)
答案 1 :(得分:29)
如果您确实需要 ConstructorInfo对象,请参阅Curt Hagenlocher's answer。
另一方面,如果你真的只是想在System.Type
的运行时创建一个对象,请参阅System.Activator.CreateInstance
- 它不仅仅是面向未来的(Activator处理更多细节)比ConstructorInfo.Invoke
),它还 更难看。
答案 2 :(得分:2)
如果您有通用类型参数,那么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表达式可能很昂贵,但如果您缓存委托并每次重用它,它可以非常快!我个人使用按类型索引的静态查找字典。当您处理序列化对象时,此函数会派上用场,您可能只知道类型信息。
注意:如果类型不可构造或没有默认构造函数,则可能会失败!
答案 3 :(得分:0)
如果您只想获取默认构造函数来实例化类,并将类型作为函数的泛型类型参数获取,则可以执行以下操作:
T NewItUp<T>() where T : new()
{
return new T();
}
答案 4 :(得分:-1)
你想尝试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
然而,如果对象具有参数化构造函数
,则此失败希望这有帮助