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

发布于 2024-10-31 02:00:43 字数 346 浏览 1 评论 0原文

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

public class A
{
    public A() {}
} 

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

I'm using Type.GetConstructor(Type.EmptyTypes) to get the default constructor for a class. It works if the class has a default constructor with no parameters (class A). But it doesn't work if a class has a constructor with all parameters optional (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 = "") {}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

早茶月光 2024-11-07 02:00:43

假设我有以下类:

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 就可以完成工作。

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? 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.

心清如水 2024-11-07 02:00:43

问题是 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;
    }
}

The problem is that the C# compiler produces this:

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;
    }
}
羅雙樹 2024-11-07 02:00:43

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

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

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());
}
愁杀 2024-11-07 02:00:43

问题在于,对于 B 来说,它没有不带参数的构造函数。

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

The problem is that, in the case of B, it does not have a constructor with no parameters.

Optional arguments are a compile time construct - in the IL, it's a constructor with 2 parameters (which are flagged with attributes). As such, there is no default constructor as far as Reflection is concerned.

贩梦商人 2024-11-07 02:00:43

要获得具有更多可选参数或根本没有空构造函数的构造函数,请使用:

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

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();
客…行舟 2024-11-07 02:00:43

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

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文