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

时间:2011-11-05 09:17:09

标签: c# reflection compiler-optimization internal

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

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

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

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

我知道两个解决方法:

  1. 使构造函数公开(但我不希望此程序集的用户使用它)。
  2. 从一些公共方法调用构造函数(我有很多像这样的类,所以我不想写很多这些丑陋无用的代码)。
  3. 这个问题有哪些更好的解决方案?

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

    谢谢,

    波阿斯。

2 个答案:

答案 0 :(得分:7)

未删除构造函数,可能在搜索构造函数时应指定标记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
)

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

答案 1 :(得分:3)

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)。)