Как создать объект типа значения или строкового типа во время выполнения с помощью Reflection

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

  object o =  PropertyType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes,null).Invoke(null);

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

  object o =  PropertyType.Type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { 0 });

который тоже отлично работает. Но когда дело доходит до строкового типа или типов значений, GetConstructor.Invoke не работает. Я также попробовал Activator.CreateInstance, который тоже не сработал.


person Erkan Y.    schedule 28.06.2010    source источник


Ответы (3)


Вы столкнулись с тем, что у типов значений на самом деле нет конструкторов без параметров. C # делает его похожим на них, но не на уровне CLR.

Activator.CreateInstance должен нормально работать с типами реальных значений:

object o = Activator.CreateInstance(typeof(int));
Console.WriteLine(o); // Prints 0

Это всегда будет давать значение по умолчанию для любого типа значения.

Теперь вы спрашиваете о строках - какую строку вы ожидаете создать? Значение по умолчанию для типа string - null, но хотите ли вы вместо этого пустую строку? Если это так, вам нужно будет указать этот код в особом регистре.

person Jon Skeet    schedule 28.06.2010
comment
Спасибо, Джон, я отредактировал свой вопрос. Я не имел в виду, что строка является типом значения ... Так как насчет создания экземпляра строки? - person Erkan Y.; 28.06.2010
comment
@Erkan: Я отредактировал свой ответ. Какую строку вы хотите создать? Если вы выберете конструктор, который действительно существует, вы, безусловно, можете вызвать его с отражением, но, конечно, вам нужно будет указать значения для параметров ... - person Jon Skeet; 28.06.2010
comment
просто хочу динамически создать экземпляр свойства класса, имеющего строковый тип, но мне не нужно нулевое значение в созданном объекте. Итак, я думаю, мне нужно сделать особый случай для свойств строкового типа в классе. Тем не менее, все еще не ясно, как создать экземпляр объекта из свойства класса строкового типа. Поскольку я сделаю особый случай: if (property.PropertyType == typeof (string)) object o =; быть достаточным? - person Erkan Y.; 28.06.2010
comment
@Erkan: Да, это сработает. Но действительно ли значение по умолчанию для всех других типов значений действительно полезно? Не могли бы вы дать немного больше информации о том, что вы собираетесь делать с ценностью? Может, есть подход получше. - person Jon Skeet; 28.06.2010

Если вы хотите иметь возможность создавать экземпляры произвольных объектов с определенными значениями, вы можете проверить, существует ли TypeConverter, который поддерживает преобразование экземпляра (со значением, которое вы хотите сопоставить) в InstanceDescriptor. Я не совсем уверен, что вы делаете (ваш пример предполагает, что вы пытаетесь создать экземпляры «по умолчанию» для различных объектов), но просто подумал, что упомянул бы об этом, если это актуально. Я использую это в коде Emit, чтобы передавать произвольные постоянные значения в стек через IL. Вот фрагмент, который получает InstanceDescriptor:

        var converter = TypeDescriptor.GetConverter(value);
        if (converter.CanConvertTo(typeof (InstanceDescriptor)))
        {
            var desc = (InstanceDescriptor) converter.ConvertTo(value, typeof (InstanceDescriptor));
        }

Дескриптор определяет способ создания экземпляра, который может вызывать конструктор, вызывать статический метод, обращаться к статическому свойству или обращаться к статическому полю. Он также указывает, полностью ли конструкция устанавливает значение типа в соответствии с исходным экземпляром; в противном случае вам нужно будет сделать дополнительное отражение и настройку свойств.

Это механизм, который WinForms Designer использует при создании кода программной части для элементов управления в форме, поэтому он поддерживается для общих типов, которые отображаются как свойства элементов управления, доступные из конструктора.

person Dan Bryant    schedule 28.06.2010

Тип int не имеет конструкторов.

Код, который вы пишете, будет зависеть от типа свойства; обычно вы пишете код особого случая для string, int и других примитивных типов.

Ваш код выше содержит литерал 0; как вы решаете, какие значения передать конструкторам?

person Tim Robinson    schedule 28.06.2010