2016-05-12 2 views
1

У меня есть два класса с добытчиками собственности толькоКак я могу использовать отражение для изменения свойств с отсутствующими сеттерами?

public class A 
{ 
    public A(string name) 
    { 
     Name = name; 
    } 
    public string Name { get; } 
    public string Value { get; set;} 
    public string Data { get; set;} 
} 

public class B 
{ 
    public B(string name) 
    { 
     Name = name; 
    } 
    public string Name { get; } 
    public string Value { get; set;} 
} 

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

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

Можно ли сделать это проще? Есть ли способ использовать отражение для копирования объектов, когда цель имеет только свойства getter?

+0

Какой смысл иметь автоматически реализованные свойства, даже если у вас нет частного сеттера? Как такой объект следует использовать без магии отражения? –

+0

Это разрешено в последней версии C#, но его можно установить только в конструкторе. Чтение только при создании. – Frode

+0

согласны, но вы устанавливаете только имя в конструкторе. Таким образом, нет никакого порядкового способа настройки 'Value' и' Data' –

ответ

0

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

Попробуйте это;

public static void CopyItem<U, T>(U source, T target) 
{ 
    // Need a way to rename the backing-field name to the property Name ("<A>k__BackingField" => "A") 
    Func<string, string> renameBackingField = key => new string(key.Skip(1).Take(key.IndexOf('>') - 1).ToArray()); 

    // Get public source properties (change BindingFlags if you need to copy private memebers as well) 
    var sourceProperties = source.GetType().GetProperties().ToDictionary(item => item.Name); 
    // Get "missing" property setter's backing field 
    var targetFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField).ToDictionary(item => renameBackingField(item.Name)); 

    // Copy properties where target name matches the source property name 
    foreach(var sourceProperty in sourceProperties) 
    { 
     if (targetFields.ContainsKey(sourceProperty.Key) == false) 
      continue; // No match. skip 

     var sourceValue = sourceProperty.Value.GetValue(source); 
     targetFields[sourceProperty.Key].SetValue(target, sourceValue); 
    } 
} 

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

Используйте CopyItem для копирования свойств исходного кода в конструкторе;

public class SomeClass 
{ 
    public SomeClass(SomeSourceClass source) 
    { 
     Helper.CopyItem(source, this); 
    } 
} 
+0

Вы уверены, что это сработает? Что, если 'T' содержит более одного номинального частного поля? В этом случае ваш вспомогательный метод вернет более одного раза пустую строку, которая приведет к дублированию ключевого исключения. Возможно, должно существовать предложение 'where', которое фильтрует поля для поддержки. BTW: похоже, что это решение также будет работать после запуска конструктора (не может его проверить). Если это правда, вы измените свойства, которые должны быть неизменными. И последнее: не забывайте о производительности. –

+0

Это, вероятно, не распространяется на все сценарии. Например, когда вы смешиваете авто-свойства с геттерами только с настраиваемыми полями поддержки. Конечно, вы можете получить некоторые сюрпризы. Особенно, когда ваши поля поддержки имеют другие имена, кроме ваших свойств. Но в большинстве случаев это сработает. Я потратил некоторое время, чтобы найти способ установить свойства только с помощью геттеров. Просто хотел поделиться :) – Frode

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