Разница между Activator.CreateInstance(string) и Activator.CreateInstance‹T›()

Нет, это не вопрос о дженериках.

У меня есть фабричный шаблон с несколькими классами с внутренними конструкторами (я не хочу, чтобы они создавались, если не через фабрику).

Моя проблема в том, что CreateInstance завершается с ошибкой «Для этого объекта не определен конструктор без параметров», если я не передам «true» для непубличного параметра.

Пример

// Fails
Activator.CreateInstance(type);

// Works
Activator.CreateInstance(type, true);

Я хотел сделать фабрику универсальной, чтобы сделать ее немного проще, например:

public class GenericFactory<T> where T : MyAbstractType
{
    public static T GetInstance()
    {
        return Activator.CreateInstance<T>();
    }
}

Однако мне не удалось найти, как передать этот «истинный» параметр, чтобы он принимал непубличные конструкторы (внутренние).

Я что-то пропустил или это невозможно?


person juan    schedule 11.09.2008    source источник
comment
Почему бы не определить конструктор без параметров с частной логической переменной, установленной в true?   -  person Vivek    schedule 20.10.2008


Ответы (3)


Чтобы обойти это, не могли бы вы просто изменить свое использование как таковое:

public class GenericFactory<T> where T : MyAbstractType
{
    public static T GetInstance()
    {
        return Activator.CreateInstance(typeof(T), true);
    }
}

Ваш фабричный метод по-прежнему будет универсальным, но вызов активатора не будет использовать универсальную перегрузку. Но вы все равно должны добиться тех же результатов.

person Kilhoffer    schedule 11.09.2008
comment
Если бы перегрузки не было, я бы сказал нет. - person Kilhoffer; 11.09.2008

Если вам абсолютно необходимо, чтобы конструктор был закрытым, вы можете попробовать что-то вроде этого:

public abstract class GenericFactory<T> where T : MyAbstractType
{
    public static T GetInstance()
    {
        return (T)Activator.CreateInstance(typeof(T), true);
    }
}

В противном случае вам лучше всего добавить новое ограничение и пойти по этому пути:

public abstract class GenericFactory<T> where T : MyAbstractType, new()
{
    public static T GetInstance()
    {
        return new T;
    }
}

Вы пытаетесь использовать GenericFactory в качестве базового класса для всех ваших фабрик, а не писать каждую с нуля, верно?

person rpetrich    schedule 11.09.2008
comment
Первый вариант такой же, как у Килхоффера. Второй не сработает, добавление new() в where требует, чтобы тип имел публичный параметр, а это именно то, чего я не хочу. - person juan; 11.09.2008
comment
Да, его пост появился, когда я печатал свой. - person rpetrich; 12.09.2008

кроме Activator.CreateInstance(typeof(T), true) для работы, T должен иметь конструктор по умолчанию

person mpastern    schedule 13.06.2010