Как предотвратить компилятор C # от удаления внутреннего конструктора - PullRequest
1 голос
/ 05 ноября 2011

У меня есть открытый класс с 2 конструкторами: по умолчанию (без параметров), который является внутренним, и другой, который является открытым.Конструктор по умолчанию вызывает другой с некоторыми значениями по умолчанию.

Я вызываю внутренний конструктор, используя отражение, поэтому он не используется нигде в сборке статически (только отражением).

Когда я делаюПри вызове отражения я получаю:

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

Я знаю два обходных пути:

  1. Сделайте конструктор общедоступным (но я не хочу, чтобы пользователи этой сборкииспользуйте его).
  2. Вызовите конструктор из какого-то открытого метода (у меня есть много классов, подобных этому, поэтому я не хочу писать много этого уродливого бесполезного кода).

Есть ли лучшие решения этой проблемы?

Стоит отметить, что если конструктор по умолчанию является общедоступным, я не получу это исключение.

Спасибо,

Боаз.

Ответы [ 2 ]

7 голосов
/ 05 ноября 2011

Конструктор не удален, вероятно, при поиске вашего конструктора вы должны указать флаг 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 (тип, истина) будет вызывать конструктор как открытый, так и закрытый \ внутренний \ защищенный.

3 голосов
/ 05 ноября 2011

Компилятор 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);
    }
}

EDIT: чтобы передать флаги привязки в Activator.CreateInstance, вам нужно использовать другую перегрузку, например:

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

(Или вы можете использовать CreateInstance(type, true), как указано в комментариях.)

...