2015-07-10 2 views
3

Предположим, класс с параметризованным конструктор как:Создать экземпляр параметризованном родового объекта со всеми параметрами, установленными в нуль

MyObject(string param1, string param2, string param2) 
{ 
    ... 
} 

У меня есть Generic метод, который возвращает экземпляр Generic Class и MyObject является одним из такие случаи.

Как создать экземпляр класса с параметризованным конструктором и передать значения null во все его параметры? Это необходимо, так как свойства родового класса заселяются на несколько позднее этапе .

Я попытался с помощью Activator как:

public static T GetGenericObject<T>() 
{ 
    T resource = (T)Activator.CreateInstance(typeof(T), null); 
    ... 
} 

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

+0

Я уверен, что вы знаете это, но это должно быть сказано: Требуя свойства в конструкторе, а затем передать нуль значения из-за того, что они могут быть заселены позже, походят на действительно плохую идею. – StriplingWarrior

ответ

5

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

var parameters = typeof(T) 
    .GetConstructors() 
    .Single() 
    .GetParameters() 
    .Select(p => (object)null) 
    .ToArray(); 
T resource = (T)Activator.CreateInstance(typeof(T), parameters); 

Обратите внимание, что это предполагает, что есть только один конструктор, и это ll работает только для ссылочных типов, поэтому он довольно хрупкий.

+0

Отличный подход!Однако я получаю «не может быть выведен из использования ..» на. Выбрать (p => null) строку – eYe

+0

@eYe: Да, я только что заметил это и обновил его. – StriplingWarrior

+0

@Bang on. Принято! – eYe

2

Используйте перегрузку, которая принимает параметры и создает массив объектов для передачи, где null представляет каждый необходимый параметр.

В свете вашего комментария вы можете, конечно, сказать, что метод создает инициализированный, но пустой массив объектов на основе фиксированного количества элементов. Однако, как упоминалось в других комментариях, это чрезвычайно опасно и вызовет у вас головные боли в будущем.

var instance = GetGenericObject<MyObject>(3); 

public static T GetGenericObject<T>(int numberOfNullParametersToPass) 
{ 
    var nullParams = new object[numberOfNullParametersToPass]; 
    T resource = (T)Activator.CreateInstance(typeof(T), nullParams); 
    return resource; 
} 

Как ваш код в настоящее время стоит, вы явно говорить Activator.CreateInstance выбрать конструктор без параметров. Указав все три аргумента (даже если они равны нулю), вы выбираете правильный конструктор.

В какой-то момент в цепочке звонков вам необходимо сообщить Activator.CreateInstance, какой конструктор выбрать. Альтернативой является выбор первого возможного конструктора.

public static T GetGenericObject<T>() 
{ 
    var paramLength = typeof(T).GetConstructors().FirstOrDefault().GetParameters().Length; 
    var parameters = new object[paramLength]; 
    T resource = (T)Activator.CreateInstance(typeof(T), parameters); 
    return resource; 
} 
+0

@eYe - вы не знаете, сколько параметров: –

+0

@eYe: Вы уверены, что все параметры всегда будут ссылочными типами? Может ли любой из них быть «int», например? – StriplingWarrior

+0

Я должен был упомянуть, что мои ошибки, параметры могут быть только строками или DateTime, поэтому да, все являются ссылочными типами. – eYe

0

Ниже простой метод без worring о параметре и избежать ошибок в construtor не существует по умолчанию

var ctors = typeof(T).GetConstructors(); 
var ctor = ctors[0]; 
var instance = ctor.Invoke(new object[ctor.GetParameters().Length]); 
+0

Пробовал это тоже -> Исключение NullRef – eYe

+0

@eYe - попробуйте обновить один –

+0

@eYe - обновлено решение работает ?? –

Смежные вопросы