我使用Type.GetConstructor(Type.EmptyTypes)
来获取类的默认构造函数。如果类有一个没有参数的默认构造函数(class A
),它就可以工作。但它不工作,如果一个类有一个构造函数与所有参数可选(class B
)。程序不知道可选参数是什么,因为它只需要默认构造函数。我可以用什么语句使它对两种情况都有效?谢谢,感谢任何帮助!
public class A
{
public A() {}
}
public class B
{
public B(int i = 0, string str = "") {}
}
假设我有以下类:
public class SomeClass
{
public SomeClass()
{
}
public SomeClass(int x)
{
}
public SomeClass(int x = 0, int y = 0)
{
}
}
基本上,您要求查询将找到与构造函数1和3匹配的构造函数?如果是,使用如下:
var constuctors = typeof(SomeClass).GetConstructors()
.Where(x => x.GetParameters().Count() == 0
|| x.GetParameters().Count(param => param.GetCustomAttributes(typeof(OptionalAttribute), false).Count() > 0) == x.GetParameters().Count());
令人难以置信的糟糕查询,但它只返回了上面的1和3。
问题是c#编译器产生了这个:
public class B
{
// Methods
public B([Optional, DefaultParameterValue(0)] int i, [Optional, DefaultParameterValue("")] string str)
{
}
}
应该像下面这样工作:
public static class TypeHelper {
public static ConstructorInfo GetDefaultConstructor<TType>() {
var type = typeof(TType);
return type.GetDefaultConstructor();
}
public static ConstructorInfo GetDefaultConstructor(this Type type) {
if(type == null) throw new ArgumentNullException("type");
var constructor = type.GetConstructor(Type.EmptyTypes);
if(constructor == null) {
var ctors =
from ctor in type.GetConstructors()
let prms = ctor.GetParameters()
where prms.All(p=>p.IsOptional)
orderby prms.Length
select ctor;
constructor = ctors.FirstOrDefault();
}
return constructor;
}
}
问题是可选参数只不过是编译时的概念。您需要完整地指定构造函数。
var ci = typeof(B).GetConstructor(new [] { typeof(int), typeof(string) });
你可以写一个帮助函数,用默认值来调用构造函数。我的例子不像它应该的那样健壮,但它应该让你开始。
static Func<T> CreateDefaultConstructor<T>(ConstructorInfo ci)
{
var l = new List<object>();
foreach (var p in ci.GetParameters())
{
if (p.IsOptional)
{
l.Add(p.RawDefaultValue);
}
}
return () => (T)ci.Invoke(l.ToArray());
}
问题在于,在B的例子中,它没有没有参数的构造函数。
可选参数是一个编译时构造——在IL中,它是一个带有2个参数的构造函数(用属性标记)。因此,就Reflection而言,没有默认构造函数。
要获得具有更多可选参数或完全为空的构造函数,请使用:
typeof(myClass)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
.FirstOrDefault();
当构造函数或任何其他方法有可选参数时,它不会导致编译器生成该方法的多个版本。相反,它生成一个具有所有指定参数的单一方法。默认值被编码在附加到方法签名的属性中。它们在调用站点使用,使它们的值成为可选的。
这里没有默认构造函数只有一个带两个参数的构造函数