How do I check if a type provides a parameterless constructor?

I'd like to check if a type that is known at runtime provides a parameterless constructor. The Type class did not yield anything promising, so I'm assuming I have to use reflection?

35270 次浏览

是的,你必须使用反射。但是当你使用 GetType()的时候你已经这样做了

比如:

var t = x.GetType();
var c = t.GetConstructor(new Type[0]);
if (c != null) ...

这应该会奏效:

   myClass.GetType().GetConstructors()
.All(c=>c.GetParameters().Length == 0)

Type反射。你可以做:

Type theType = myobject.GetType(); // if you have an instance
// or
Type theType = typeof(MyObject); // if you know the type


var constructor = theType.GetConstructor(Type.EmptyTypes);

如果不存在无参数构造函数,它将返回 null。


如果还希望查找私有构造函数,请使用稍长的:

var constructor = theType.GetConstructor(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null, Type.EmptyTypes, null);

对于值类型有一个警告,即 不允许有缺省构造函数。您可以使用 Type.IsValueType属性检查是否有值类型,并使用 Activator.CreateInstance(Type)创建实例;

是的,你必须使用反射。

object myObject = new MyType();
Type type = myObject.GetType();
ConstructorInfo conInfo = type.GetConstructor(new Type[0]);

根据您的情况,您还可以使用泛型类型限制:

public void DoSomethingWith<T>(T myObject) where T:new() {...}

上面的方法声明将把参数类型限制为可以用无参数构造函数实例化的任何 Object。这里的优势在于,编译器将捕获任何尝试使用没有无参数构造函数的类的方法,所以只要类型在编译时是已知的 SOMEWHERE,这将工作,并提醒您一个问题。

当然,如果类型真的只在运行时知道(例如,您正在使用 Activator。创建实例()来实例化基于字符串或构造类型的对象,那么这对您没有帮助。我通常把反射作为绝对的最后选择,因为一旦你到达了动态的地方,你就必须停留在动态的地方; 动态实例化一些东西,然后开始静态处理它通常是困难的,甚至是混乱的。

type.GetConstructor(Type.EmptyTypes) != null

structs 会失败。最好延长它:

public static bool HasDefaultConstructor(this Type t)
{
return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

成功,因为甚至 enum都有默认的无参数构造函数。由于没有进行反射调用,值类型的速度也略有加快。

我需要使用与真正的无参数构造函数相同的 只有可选参数来计算构造函数:

myClass.GetType().GetConstructors()
.All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional))

If anyone is interested in an "official" version, the following was found via .NET Reflector:

发信人: 系统、活动、表示、类型实用程序
在 < strong > System. Activity. Presentation.dll,Version = 4.0.0.0中

public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) =>
t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;

注意 t.IsAbstract的支票,这在本页的其他地方没有提到。

如果你想对一个堆栈帧进行微优化,你也可以像下面这样扩展 GetConstructor调用:

…t.GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Type.EmptyTypes, null)…

若要获得具有更多可选参数或者根本就是空构造函数的函数,请使用:

    typeof(myClass)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
.FirstOrDefault();