我有一个类型(人类),我想知道我是否可以System.Activator.CreateInstance(Of Human)()
。所以基本上我想检查Human是否有一个公共无参数构造函数/或带有可选参数的公共构造函数,这些参数可以在不给出任何参数的情况下调用New Human
。
是否有可能事先检查System.Activator.CreateInstance(Of T)
是否会失败? (我的意思是除了将语句System.Activator.CreateInstance(Of Human)()
包装在Try Catch中当然......)
我试过这个,但它不起作用:
Option Strict On : Option Explicit On
Module Test
Public Class Human
Public Sub New(Optional ByVal a As Integer = 1)
End Sub
End Class
Public Sub Main()
Dim c = GetType(Human).GetConstructor(System.Type.EmptyTypes)
MsgBox(c Is Nothing)
End Sub
End Module
答案 0 :(得分:7)
检查构造函数是否为空或所有参数都是可选的:
var hasEmptyOrDefaultConstr =
typeof(Human).GetConstructor(Type.EmptyTypes) != null ||
typeof(Human).GetConstructors(BindingFlags.Instance | BindingFlags.Public)
.Any (x => x.GetParameters().All (p => p.IsOptional));
答案 1 :(得分:3)
您可以检查并确保您的类型Human
具有可访问的无参数构造函数。最简单的方法是创建一个通用方法并添加约束where T : new()
编辑:
您可以像这样手动检查无参数构造函数
if(typeof(Human).GetType().GetConstructor(Type.EmptyTypes) !=null)
{
...
}
答案 2 :(得分:3)
请注意,Activator.CreateInstance<T>()
或Activator.CreateInstance(Type)
仅适用于无参数构造函数。在这个意义上,只有可选参数的构造函数 not 无参数。
可选参数(或参数)由调用站点上的C#编译器解析。但是,在使用反射调用构造函数时,没有编译器涉及这种方式。
如果您使用以下代码,则会得到一个MissingMethodException
,表示没有定义无参数构造函数:
namespace ConsoleApplication1
{
public class Foo
{
public Foo(int optional = 42)
{
}
}
class Program
{
static void Main(string[] args)
{
Activator.CreateInstance<Foo>(); // causes MissingMethodException
}
}
}
换句话说,可选参数是编译器,而不是CLR。
有关“带有可选参数的极端情况”的更多信息,请参阅Eric Lippert最近的博客系列:
http://ericlippert.com/2011/05/09/optional-argument-corner-cases-part-one/
说到这一点,你可能能够以某种方式使用更多的反射来复制所需的行为,并为构造函数调用手动创建所需的参数。编译器会在程序集中放置一些可用于此目的的属性,我猜。
示例:
public class Foo
{
public Foo([Optional, DefaultParameterValue(5)] int optional)
{
Console.WriteLine("Constructed");
}
}
答案 3 :(得分:1)
我使用反射创建了一个快速控制台应用程序,以测试类型上的无参数构造函数。这是你需要的吗?
using System;
using System.Linq;
namespace ConsoleApplication
{
public class HasPublicParameterlessContructorClass
{
}
public class DoesntHavePublicParameterlessContructorClass
{
private int someField;
public DoesntHavePublicParameterlessContructorClass(int someParameter)
{
someField = someParameter;
}
}
class Program
{
public static bool HasPublicParameterlessContructor(Type t)
{
return t.GetConstructors().Any(constructorInfo => constructorInfo.GetParameters().Length == 0);
}
static void Main()
{
Console.WriteLine(HasPublicParameterlessContructor(typeof(HasPublicParameterlessContructorClass)));
Console.WriteLine(HasPublicParameterlessContructor(typeof(DoesntHavePublicParameterlessContructorClass)));
}
}
}