将对象值复制到另一种类型的对象的简单方法?

时间:2011-06-15 00:56:46

标签: c# .net reflection .net-4.0

我一直在寻求通过指定我打算充当容器的基础数据模型使我的应用程序更具可扩展性,以便发送到另一个应用程序的数据始终具有正确的结构。

但是我希望将来能够轻松地从XML和数据库等来源加载数据,所以我想知道如何将一个对象的值复制到基础数据模型对象,其中对象是im复制来自的值可能不是相同的结构(因此我主要只想匹配属性名称)。

以下是我的尝试:

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 个答案:

答案 0 :(得分:4)

尝试使用AutoMapper。它映射具有匹配属性名称的不同类型,并且还有几个方法可以使用表达式来自定义映射

答案 1 :(得分:4)

如果我理解你的问题,你可能想看看像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更喜欢

答案 2 :(得分:1)

你走在正确的轨道上。您可以使用extension methods使用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>作为MergeFromLoadFrom,扩展方法可以为您提供相当大的灵活性。