Установить свойство объекта с помощью отражения

Есть ли способ в C # 3.5, где я могу использовать reflection для установки свойства объекта?

Пример:

MyObject obj = new MyObject(); obj.Name = "Value"; 

Я хочу установить obj.Name с reflectionм. Что-то вроде:

 Reflection.SetProperty(obj, "Name") = "Value"; 

Есть ли способ сделать это?

Да, вы можете использовать Type.InvokeMember() :

 using System.Reflection; MyObject obj = new MyObject(); obj.GetType().InvokeMember("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, Type.DefaultBinder, obj, "Value"); 

Это вызовет исключение, если obj не имеет свойства с именем Name или его невозможно установить.

Другой подход – получить метаданные для свойства, а затем установить его. Это позволит вам проверить наличие свойства и убедиться, что он может быть установлен:

 using System.Reflection; MyObject obj = new MyObject(); PropertyInfo prop = obj.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance); if(null != prop && prop.CanWrite) { prop.SetValue(obj, "Value", null); } 

Вы также можете сделать:

 Type type = target.GetType(); PropertyInfo prop = type.GetProperty("propertyName"); prop.SetValue (target, propertyValue, null); 

где target – объект, который будет иметь свой набор свойств.

Отражение, в основном, т.е.

 myObject.GetType().GetProperty(property).SetValue(myObject, "Bob", null); 

или есть библиотеки, которые помогут как с точки зрения удобства, так и с точки зрения производительности; например, с FastMember :

 var wrapped = ObjectAccessor.Create(obj); wrapped[property] = "Bob"; 

(что также имеет то преимущество, что не нужно заранее знать, является ли это полем и свойством)

Или вы можете перенести один лайнер Marc в свой собственный class расширения:

 public static class PropertyExtension{ public static void SetPropertyValue(this object obj, string propName, object value) { obj.GetType().GetProperty(propName).SetValue(obj, value, null); } } 

и назовите его так:

 myObject.SetPropertyValue("myProperty", "myValue"); 

Для хорошей меры добавим метод для получения значения свойства:

 public static object GetPropertyValue(this object obj, string propName) { return obj.GetType().GetProperty(propName).GetValue (obj, null); } 

Да, используя System.Reflection :

 using System.Reflection; ... string prop = "name"; PropertyInfo pi = myObject.GetType().GetProperty(prop); pi.SetValue(myObject, "Bob", null); 

Вы также можете получить доступ к полям с помощью simillar:

 var obj=new MyObject(); FieldInfo fi = obj.GetType(). GetField("Name", BindingFlags.NonPublic | BindingFlags.Instance); fi.SetValue(obj,value) 

С reflectionм все может быть открытой книгой 🙂 В моем примере мы привязываемся к полю уровня частного экземпляра.

Используйте что-то вроде этого:

 public static class PropertyExtension{ public static void SetPropertyValue(this object p_object, string p_propertyName, object value) { PropertyInfo property = p_object.GetType().GetProperty(p_propertyName); property.SetValue(p_object, Convert.ChangeType(value, property.PropertyType), null); } } 

или

 public static class PropertyExtension{ public static void SetPropertyValue(this object p_object, string p_propertyName, object value) { PropertyInfo property = p_object.GetType().GetProperty(p_propertyName); Type t = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; object safeValue = (value == null) ? null : Convert.ChangeType(value, t); property.SetValue(p_object, safeValue, null); } } 

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

 public static void Assign(this object destination, object source) { if (destination is IEnumerable && source is IEnumerable) { var dest_enumerator = (destination as IEnumerable).GetEnumerator(); var src_enumerator = (source as IEnumerable).GetEnumerator(); while (dest_enumerator.MoveNext() && src_enumerator.MoveNext()) dest_enumerator.Current.Assign(src_enumerator.Current); } else { var destProperties = destination.GetType().GetProperties(); foreach (var sourceProperty in source.GetType().GetProperties()) { foreach (var destProperty in destProperties) { if (destProperty.Name == sourceProperty.Name && destProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType)) { destProperty.SetValue(destination, sourceProperty.GetValue(source, new object[] { }), new object[] { }); break; } } } } 

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

Вот пакет

Устанавливает значение свойства объекта по его пути из корня.

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

Применение:

Для настройки свойств непосредственно под корнем объекта:

То есть. Класс LineItem имеет свойство int, называемое ItemId

 LineItem lineItem = new LineItem(); ObjectWriter.Set(lineItem, "ItemId", 13, delimiter: null); 

Для установки вложенного свойства несколько уровней ниже корня объекта:

То есть. Invite classе Invite есть свойство State , которое имеет свойство Invite (типа приглашения), которое имеет свойство Recipient , которое имеет свойство Id .

Чтобы сделать вещи еще более сложными, свойство State не является ссылочным типом, это struct .

Вот как вы можете установить свойство Id (в строковое значение «outlook») в нижней части дерева объектов в одной строке.

 Invite invite = new Invite(); ObjectWriter.Set(invite, "State_Invite_Recipient_Id", "outlook", delimiter: "_"); 

Основываясь на предложении MarcGravell, я построил следующий статический метод. Этот метод в общем случае присваивает всем подходящим свойствам исходного объекта цели, используя FastMember

  public static void DynamicPropertySet(object source, object target) { //SOURCE var src_accessor = TypeAccessor.Create(source.GetType()); if (src_accessor == null) { throw new ApplicationException("Could not create accessor!"); } var src_members = src_accessor.GetMembers(); if (src_members == null) { throw new ApplicationException("Could not fetch members!"); } var src_class_members = src_members.Where(x => x.Type.IsClass && !x.Type.IsPrimitive); var src_class_propNames = src_class_members.Select(x => x.Name); var src_propNames = src_members.Except(src_class_members).Select(x => x.Name); //TARGET var trg_accessor = TypeAccessor.Create(target.GetType()); if (trg_accessor == null) { throw new ApplicationException("Could not create accessor!"); } var trg_members = trg_accessor.GetMembers(); if (trg_members == null) { throw new ApplicationException("Could not create accessor!"); } var trg_class_members = trg_members.Where(x => x.Type.IsClass && !x.Type.IsPrimitive); var trg_class_propNames = trg_class_members.Select(x => x.Name); var trg_propNames = trg_members.Except(trg_class_members).Select(x => x.Name); var class_propNames = trg_class_propNames.Intersect(src_class_propNames); var propNames = trg_propNames.Intersect(src_propNames); foreach (var propName in propNames) { trg_accessor[target, propName] = src_accessor[source, propName]; } foreach (var member in class_propNames) { var src = src_accessor[source, member]; var trg = trg_accessor[target, member]; if (src != null && trg != null) { DynamicPropertySet(src, trg); } } } 
  • В чем разница между иварами и свойствами в Objective-C
  • Как проверить, имеет ли объект определенный метод / свойство?
  • Как получить значение свойства bean, когда само имя свойства является динамической переменной
  • Имущество (без дополнительной обработки) против публичного поля
  • Как получить список свойств classа?
  • Безопасность streamа C # с get / set
  • appSettings vs applicationSettings. appSettings устарел?
  • Свойство getter / setter не влияет на Python 2
  • Почему открытые поля быстрее, чем свойства?
  • Когда для доступа к свойствам с помощью «self»
  • Есть ли причина объявлять ivars, если вы используете свойства исключительно в Objective-C?
  • Interesting Posts

    Нажмите внешнее меню, чтобы закрыть в jquery

    Возrotation анонимного типа в C #

    Возможно ли сбросить перечисление виртуальных com-портов FTDI, мы легко получаем сотни COM-портов в производственной среде

    Стиль ввода флажков CSS

    Начало работы с Windows Phone 7

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

    ITerm2 теряет цвета «ls», если я ssh на сервере

    Присоедините много файлов MP3, OGG и FLAC в один WAV или FLAC

    Как обнулить последовательность целых чисел в bash, чтобы все имели одинаковую ширину?

    Разница между методами добавления и расширения списка в Python

    Как изменить режим браузера в IE9 на постоянной основе?

    Почему мой USB-hdd возвращает данные SG_IO: bad / missing sense?

    Как программно отключить режим быстрого редактирования C # консольного приложения?

    Почему мой Transform привязывается назад?

    Время компиляции и время выполнения c #

    Давайте будем гением компьютера.