2014-01-21 3 views
1

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

На самом деле, я могу использовать ручной сопоставление. Я знаю, но это должно работать для каждого класса, который назвал эту функцию. Я прочитал, что lambda expression может быть моим решением, но я не знаю, как я могу писать это в целом и динамически для каждого интерфейса/класса.

Мой вопрос состоит в том, чтобы не создавать новый экземпляр, а использовать существующий экземпляр. У кого-нибудь есть идея?

+0

Использование отражения для запуска через свойство «малый» типа. Для каждого найдите свойство с тем же именем в «большом» типе. Прочтите из своего экземпляра большого типа и напишите в новый экземпляр небольшого типа. –

ответ

3

Если вы не против использования стороннего инструмента, AutoMapper делает это довольно хорошо.

Пример взят из AutoMapper документации:

Mapper.CreateMap<Order, OrderDto>(); 
OrderDto dto = Mapper.Map<OrderDto>(order); 
2

Если вы не возражаете, используя сторонний инструмент, вы можете использовать этот фрагмент кода и адаптироваться по мере необходимости:

public B Convert<A, B>(A element) where B : A, new() 
{ 
    //get the interface's properties that implement both a getter and a setter 
    IEnumerable<PropertyInfo> properties = typeof(A) 
     .GetProperties() 
     .Where(property => property.CanRead && property.CanWrite).ToList(); 

    //create new object 
    B b = new B(); 

    //copy the property values to the new object 
    foreach (var property in properties) 
    { 
     //read value 
     object value = property.GetValue(element); 

     //set value 
     property.SetValue(b, value); 
    } 

    return b; 
} 
+0

Для примера, если 'B' фактически не вытекает из' A', то он может хранить имена свойств и проверять, что другой тип также имеет свойство под этим именем. –

+1

@JeppeStigNielsen Это правда. Код предполагает, что оба класса реализуют один и тот же интерфейс, как указано OP. Дальнейшая проверка может быть добавлена, в зависимости от конкретного варианта использования. – dcastro

+0

Или: 'общественная пустота Копировать (T от Т к), где T: класс { /* получить свойства этого интерфейса, которые реализуют как геттер и сеттер */ IEnumerable свойства = TypeOf (T) .GetProperties() .Where (свойство => свойство.CanRead && property.CanWrite) .ToList(); /* скопировать значения свойств на новый объект */ Еогеасп (вар свойств в свойствах) { /* считанное значение */ значение объекта = property.GetValue (с); /* установленное значение */ property.SetValue (to, value); } } '. Используйте как: 'var b = new B(); Скопируйте (element, b); ' –

0
public static void BusinessObjectConverter<TTarget, TSource>(this TTarget target, TSource source) 
    { 
     //Lesen aller Properties auf der ersten Ebene 
     var targetProperties = typeof(TTarget) 
      .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) 
      .Where(prop => prop.CanWrite); 

     //Lesen aller Properties auf der ersten Ebene 
     var sourceProperties = typeof(TTarget) 
      .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) 
      .Where(prop => prop.CanWrite); 

     //Loop durch alle Properties 
     foreach (var item in targetProperties.Intersect(sourceProperties)) 
     { 
      //Leere Werte duerfen nicht geschrieben werden 
      if (!string.IsNullOrEmpty(source.GetType().GetProperty(item.Name).GetValue(source, null).ToString())) 
      { 
       //Befuellen der Properties im Zielobjekt 
       item.SetValue(target, ValueConverter.ConvertValue(
        source.GetType().GetProperty(item.Name).GetValue(source, null), 
        item.PropertyType), 
        null); 
      } 
     } 
    } 
+0

Это будет работать для меня ... Он расширяет объекты, и я могу обновлять поля для записи в базе данных. – DMR

0

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

Следуя от ответа Automapper, может быть больно вручную создавать сопоставления. Для того, чтобы сделать это динамически я использую:

TDestination destination = new TDestination();    
AutoMapper.Mapper.Map<TSource, TDestination>(source, destination, opts => opts.CreateMissingTypeMaps = true); 

Все, что вам нужно помнить, чтобы сделать это, чтобы убедиться, что имена свойств соответствуют

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