如何防止 C# 编译器删除内部构造函数

发布于 2024-12-13 23:34:28 字数 475 浏览 1 评论 0原文

我有一个带有 2 个构造函数的公共类:默认的(不带参数)是内部的,另一个是公共的。 默认构造函数使用一些默认值调用另一个构造函数。

我使用反射调用内部构造函数,因此它不会在程序集中的任何地方静态使用(仅通过反射)。

当我进行反射调用时,我得到:

System.MissingMethodException
    Message=No parameterless constructor defined for this object.

我知道两种解决方法:

  1. 将构造函数公开(但我不希望此程序集的用户使用它)。
  2. 从某个公共方法调用构造函数(我有很多像这样的类,所以我不想编写很多这种丑陋无用的代码)。

对于这个问题有更好的解决方案吗?

值得一提的是,如果默认构造函数是公共的,我不会得到该异常。

谢谢,

波阿斯。

I have a public class with 2 constructors: The default (without parameters), which is internal, and a different one, which is public.
The default constructor calls the other one with some default values.

I call the internal constructor using reflection, so it's not used anywhere in the assembly statically (only by reflection).

When I make the reflection call, I'm getting:

System.MissingMethodException
    Message=No parameterless constructor defined for this object.

I know of two workarounds:

  1. Make the constructor public (but I don't want the users of this assembly to use it).
  2. Call the constructor from some public method (I have many classes like this one, so I don't want to write a lot of this ugly useless code).

Any better solutions to this problem?

It's worth mentioning that if the default constructor is public, I don't get that exception.

Thanks,

Boaz.

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

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

发布评论

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

评论(2

鹿港小镇 2024-12-20 23:34:28

构造函数未删除,可能在搜索构造函数时您应该指定标志 BindingFlag.NonPublic

    class xxx
    {
        private xxx() :
            this(10)
        {
        }

        public xxx(int value)
        {
            Console.WriteLine(value);
        }
    }

    static void Main(string[] args)
    {
        Activator.CreateInstance(typeof(xxx), true);
        Console.ReadLine();
    }

Activator.CreateInstance 有一个带有布尔值的重载,您可以在其中指定是否要调用非公共构造函数。

public static Object CreateInstance(
    Type type,
    bool nonPublic
)

如果构造函数是 public 或 private\internal\protected,Activator.CreateInstance(type, true) 将调用构造函数。

The constructor is not removed, probably in the search of your constructor you should specify the flag BindingFlag.NonPublic.

    class xxx
    {
        private xxx() :
            this(10)
        {
        }

        public xxx(int value)
        {
            Console.WriteLine(value);
        }
    }

    static void Main(string[] args)
    {
        Activator.CreateInstance(typeof(xxx), true);
        Console.ReadLine();
    }

Activator.CreateInstance have an overload with a boolean where you can specify if you want to call a non public constructor.

public static Object CreateInstance(
    Type type,
    bool nonPublic
)

Activator.CreateInstance(type, true) will call the constructor both if it is public or private\internal\protected.

十二 2024-12-20 23:34:28

C# 编译器不会为您删除任何构造函数。在 Reflector 中打开程序集,我相信您会看到您创建的构造函数。

我认为您用来查找构造函数的反射代码更有可能不包含 BindingFlags.NonPublic。示例代码展示它如何工作:

using System;
using System.Reflection;

class Foo
{
    internal Foo()
    {
        Console.WriteLine("Foo constructor");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Foo).GetConstructor
            (BindingFlags.NonPublic |
             BindingFlags.Public |
             BindingFlags.Instance,
             binder: null,
             types: new Type[0],
             modifiers: null);
        ctor.Invoke(null);
    }
}

编辑:要将绑定标志传递给 Activator.CreateInstance,您需要使用不同的重载,如下所示:(

Activator.CreateInstance(typeof(Foo),                                 
                         BindingFlags.NonPublic |
                         BindingFlags.Public |
                         BindingFlags.Instance,
                         binder: null,
                         args: null,
                         culture: null);

或者您可以使用评论中提到的 CreateInstance(type, true) 。)

The C# compiler does not remove any constructors for you. Open up the assembly in Reflector and I'm sure you'll see the constructors you've created.

I think it's rather more likely that the reflection code you're using to find the constructor isn't including BindingFlags.NonPublic. Sample code to show how it can work:

using System;
using System.Reflection;

class Foo
{
    internal Foo()
    {
        Console.WriteLine("Foo constructor");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Foo).GetConstructor
            (BindingFlags.NonPublic |
             BindingFlags.Public |
             BindingFlags.Instance,
             binder: null,
             types: new Type[0],
             modifiers: null);
        ctor.Invoke(null);
    }
}

EDIT: To pass binding flags to Activator.CreateInstance, you need to use a different overload, like this:

Activator.CreateInstance(typeof(Foo),                                 
                         BindingFlags.NonPublic |
                         BindingFlags.Public |
                         BindingFlags.Instance,
                         binder: null,
                         args: null,
                         culture: null);

(Or you can use the CreateInstance(type, true) as mentioned in comments.)

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