Вопрос по c#, dynamically-generated, types, reflection, generics – Создание общих переменных из типа - Как? Или используйте Activator.CreateInstance () со свойствами {} вместо параметров ()?

6

В настоящее время я использую Generics для создания некоторых динамических методов, таких как создание объекта и заполнение свойств значениями.

Есть ли способ «динамически»? создать общий, не зная типа? Например:

List<String> = new List<String>()

это предопределенный способ, но

List<(object.GetType())> = new List<(object.GetType()>()

не работает ... Но так ли это?

Это не работает (Есть ли похожий подход, который работает?)

    public T CreateObject<T>(Hashtable values)
    {
        // If it has parameterless constructor (I check this beforehand)
        T obj = (T)Activator.CreateInstance(typeof(T));

        foreach (System.Reflection.PropertyInfo p in typeof(T).GetProperties())
        {
            // Specifically this doesn't work
            var propertyValue = (p.PropertyType)values[p.Name];
            // Should work if T2 is generic
            // var propertyValue = (T2)values[p.Name];

            obj.GetType().GetProperty(p.Name).SetValue(obj, propertyValue, null);
        }
    }

Итак, вкратце: как взять & quot; Тип & quot; и создать объект из этого без использования Generics? До сих пор я использовал только Generics в методах, но возможно ли использовать то же самое для переменных? Я должен определить Generic (T) перед методом, так что я могу сделать то же самое для переменных перед & quot; созданием & quot; их?

... или как использовать & quot; Активатор & quot; создать объект со свойствами вместо параметров. Как вы делаете здесь:

// со значениями параметров

Test t = new Test("Argument1", Argument2);

// со свойствами

Test t = new Test { Argument1 = "Hello", Argument2 = 123 };

Ваш Ответ

3   ответа
5

Вы можете использоватьMakeGenericType метод для получения универсального типа для определенного аргумента типа:

var myObjListType = typeof(List<>).MakeGenericType(myObject.GetType());
var myObj = Activator.CreateInstance(myObjListType);
// MyObj will be an Object variable whose instance is a List<type of myObject>
Но, скажем, объект, который я создаю, является & quot; String, boolean, int, float ... & quot; не обязательно класс. Если затем мне нужно установить значение для него, прежде чем устанавливать для свойства objects значение. Deukalion
Для типов значений вам не нужно устанавливать значение - они автоматически имеют действительное значение по умолчанию. Например, поле типаbool не нужно инициализировать вfalseпотому что это происходит автоматически. Для строк они начинаются с нуля. Если вы хотите, чтобы они имели другое значение, например & quot; Fred & quot ;, вам нужно установить их значение & quot; Fred & quot ;. НеPerson.FirstName = new String("Fred");, увидеть?
1

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

Код выше близок - ноvar здесь не сработает, поскольку это всего лишь вывод типа времени компиляции. Поскольку вы уже используете рефлексию, вы можете просто использоватьSystem.Object:

object propertyValue = values[p.Name];

SetValue вызов будет хорошо работать сSystem.Object.

@Deukalion Но отражение - это функция CLR / Framework, а не функция языка ...
@Deukalion Тип, который вы генерируете, не имеет конструктора без параметров - так что вы не можете использовать этот метод вместе с ним ...
... и теги для моего вопроса включают "C #". Deukalion
String str = "Foo"; синтаксис является функцией языка C #, а не функцией CLR.
Итак, как я могу использовать Activator.CreateInstance с & quot; Инициализатором объекта & quot; как аргумент? Я получаю сообщение об ошибке: «Для этого объекта не определен конструктор без параметров». Типы свойств, к которым я пытаюсь добавить значения: String, Double, enum, bool. Тип, на который он не работает, - "String". У него нет конструктора без параметров, поэтому я не могу создать String и добавить к нему значение, но как это может быть, поскольку я могу определить: String str; или String str = & quot; Это строка & quot ;; Deukalion
13

Ты можешь использоватьMakeGenericType:

Type openListType = typeof(List<>);
Type genericListType = openListType.MakeGenericType(obj.GetType());
object instance = Activator.CreateInstance(genericListType);
Я не хочу использовать "Список" в этом случае это должен быть любой объект. & Quot; Тип openListType = typeof (неизвестный тип); & quot; Deukalion
Я не вижу, как этот ответ решает ОП "использовать Activator.CreateInstance () со свойствами {} вместо параметров ()?"

Похожие вопросы