Простой способ скопировать значения объекта в объект другого типа? - PullRequest
0 голосов
/ 15 июня 2011

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

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

Вот что я попробовал:

public Dictionary<string, object> ObjectValues(object source)
    {
        if(source == null)
            return null;

        Dictionary<string, object> properties = new Dictionary<string, object>();
        foreach (PropertyInfo propInfo in source.GetType().GetProperties())
        {
            try
            {
                object value = propInfo.GetValue(source, null);
                properties.Add(propInfo.Name, value);
                if (!value.GetType().IsPrimitive && !value.GetType().IsValueType)
                {
                    Dictionary<string, object> internalProperties = ProxyValues(value);
                    if (internalProperties != null)
                        foreach (KeyValuePair<string, object> internalProp in internalProperties)
                            properties.Add(String.Format("{0}.{1}", propInfo.Name, internalProp.Key), internalProp.Value);
                }
            }
            catch (TargetParameterCountException) { }
        }
        return properties;
    }

Спасибо, Алекс.

Ответы [ 3 ]

4 голосов
/ 15 июня 2011

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

Вы настроили конфигурации:

Mapper.CreateMap<TypeA, TypeB>().ForMember(dest => dest.PropB, opt => opt.MapFrom(src => src.PropA));

, который создаст отображение из TypeA в TypeB, где свойство PropA будет скопировано в PropB. Затем, когда вы хотите использовать сопоставление:

TypeA a = new TypeA();
TypeB b = new TypeB();

Mapper.Map(a, b);

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

Существует также ValueInjecter , который некоторые люди предпочитают AutoMap

4 голосов
/ 15 июня 2011

Попробуйте AutoMapper. Он отображает разнородные типы, которые имеют совпадающие имена свойств, а также имеет несколько методов, которые принимают выражения для настройки отображений

1 голос
/ 15 июня 2011

Вы на правильном пути. Что вы можете сделать, это использовать методы расширения для расширения базового типа object с помощью функции merge. Подобные вещи относительно тривиально написать самому. Вот один, который я использую:

/// <summary>
/// Merges the equivalent properties from the source to this object.
/// </summary>
/// <typeparam name="T">Any reference type.</typeparam>
/// <param name="destination">This object, which receives the values.</param>
/// <param name="source">The source object that the values are taken from.</param>
public static void MergeFrom<T>(this object destination, T source)
{
    Type destinationType = destination.GetType();
    PropertyInfo[] propertyInfos = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (var propertyInfo in propertyInfos)
    {
        PropertyInfo destinationPropertyInfo = destinationType.GetProperty(propertyInfo.Name, BindingFlags.Public | BindingFlags.Instance);
        if (destinationPropertyInfo != null)
        {
            if (destinationPropertyInfo.CanWrite && propertyInfo.CanRead && (destinationPropertyInfo.PropertyType == propertyInfo.PropertyType))
            {
                object o = propertyInfo.GetValue(source, null);
                destinationPropertyInfo.SetValue(destination, o, null);
            }
        }
    }
}

использовать довольно просто:

obj1.MergeFrom(obj2);

объединит похожие свойства из obj2 обратно в obj1, используя только эквивалентные имена и типы свойств. Обратите внимание на отсутствие обработки исключений - это специально, если это не удается, я хочу знать об этом, а не обрабатывать и глотать исключения.

Вы также можете взять эту концепцию и поместить ее непосредственно в Dictionary<string, object> либо как MergeFrom, либо как LoadFrom, методы расширения дают вам немного гибкости.

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