当参数是可选的时,如何获取默认构造函数



我使用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();

当构造函数或任何其他方法有可选参数时,它不会导致编译器生成该方法的多个版本。相反,它生成一个具有所有指定参数的单一方法。默认值被编码在附加到方法签名的属性中。它们在调用站点使用,使它们的值成为可选的。

这里没有默认构造函数只有一个带两个参数的构造函数

相关内容

  • 没有找到相关文章

最新更新