简体   繁体   English

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

[英]How to get default constructor when parameters are optional

I'm using Type.GetConstructor(Type.EmptyTypes) to get the default constructor for a class.我正在使用Type.GetConstructor(Type.EmptyTypes)来获取类的默认构造函数。 It works if the class has a default constructor with no parameters ( class A ).如果该类有一个没有参数的默认构造函数( class A ),它就可以工作。 But it doesn't work if a class has a constructor with all parameters optional ( class B ).但是如果一个类有一个所有参数都是可选的构造函数( class B ),它就不起作用。 Program doesn't know what the optional parameters are because it only needs the default constructor.程序不知道可选参数是什么,因为它只需要默认构造函数。 What can statements can I use to make it work for both cases?我可以使用哪些语句来使其适用于这两种情况? Thanks, appreciate any help!谢谢,感谢任何帮助!

public class A
{
    public A() {}
} 

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

Say I have the following class:说我有以下课程:

public class SomeClass
{
    public SomeClass()
    {

    }

    public SomeClass(int x)
    {
    }

    public SomeClass(int x = 0, int y = 0)
    {

    }
}

Basically, you're asking for a query that will find the constructors that match constructor 1 and 3 above?基本上,您要求的查询将找到与上面的构造函数 1 和 3 匹配的构造函数? If so, use this:如果是这样,使用这个:

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

Incredibly nasty query, but it gets the job done returning only 1 and 3 above.令人难以置信的令人讨厌的查询,但它完成了仅返回上面的 1 和 3 的工作。

The problem is that optional parameters are nothing more than a compile time concept.问题是可选参数只不过是一个编译时概念。 You'll need to specify the constructor completely.您需要完全指定构造函数。

var ci = typeof(B).GetConstructor(new [] { typeof(int), typeof(string) });

You can write a help function that will invoke the constructor with the default values though.您可以编写一个帮助函数,该函数将使用默认值调用构造函数。 My example is not as robust as it should be but it should get you started.我的示例并不像它应该的那样健壮,但它应该可以帮助您入门。

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

The problem is that the C# compiler produces this:问题是 C# 编译器产生了这个:

public class B
{
    // Methods
    public B([Optional, DefaultParameterValue(0)] int i, [Optional, DefaultParameterValue("")] string str)
    {
    }
}

Something like below should work:像下面这样的东西应该有效:

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

The problem is that, in the case of B, it does not have a constructor with no parameters.问题是,在 B 的情况下,它没有不带参数的构造函数。

Optional arguments are a compile time construct - in the IL, it's a constructor with 2 parameters (which are flagged with attributes).可选参数是一个编译时构造 - 在 IL 中,它是一个带有 2 个参数(用属性标记)的构造函数。 As such, there is no default constructor as far as Reflection is concerned.因此,就反射而言,没有默认构造函数。

To get the one that has more optional parameters or an empty constructor at all, use:要获得具有更多可选参数或完全为空的构造函数,请使用:

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

When a constructor, or any other method, has optional arguments it doesn't cause the compiler to generate multiple versions of the method.当构造函数或任何其他方法具有可选参数时,它不会导致编译器生成该方法的多个版本。 Instead it generates a single method which has all of the specified parameters.相反,它生成一个具有所有指定参数的方法。 The default values are encoded in attributes attached to the method signature.默认值编码在附加到方法签名的属性中。 These are used at the call site to make their values optional.这些在调用站点使用以使其值可选。

So here there is no default constructor but instead a single one with 2 parameters所以这里没有默认构造函数,而是一个带有 2 个参数的构造函数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM