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

时间:2011-04-07 19:01:42

标签: c# reflection constructor

我正在使用Type.GetConstructor(Type.EmptyTypes)来获取类的默认构造函数。如果类具有没有参数的默认构造函数(class A),则它可以工作。但是如果一个类的构造函数具有可选的所有参数(class B),则它不起作用。程序不知道可选参数是什么,因为它只需要默认构造函数。我可以使用哪些语句使其适用于这两种情况?谢谢,感谢任何帮助!

public class A
{
    public A() {}
} 

public class B
{
    public B(int i = 0, string str = "") {}
}

6 个答案:

答案 0 :(得分:6)

说我有以下课程:

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。

答案 1 :(得分:3)

问题是可选参数只不过是编译时的概念。您需要完全指定构造函数。

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());
}

答案 2 :(得分: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;
    }
}

答案 3 :(得分:2)

问题是,在B的情况下,它没有没有参数的构造函数。

可选参数是一个编译时构造 - 在IL中,它是一个带有2个参数的构造函数(用属性标记)。因此,就Reflection而言,没有默认的构造函数。

答案 4 :(得分:0)

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

所以这里没有默认构造函数,而是一个带有2个参数的单一构造函数

答案 5 :(得分:0)

要获取具有更多可选参数或完全没有构造函数的参数,请使用:

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