C# 将值从一个对象复制到另一个对象

C# 将值从一个对象复制到另一个对象,c#,C#,有人建议使用一个好的实用程序类将值从一个对象映射到另一个对象吗?我想要一个实用程序类,它使用反射并获取两个对象,如果存在同名的公共属性,则将值从第一个对象复制到第二个对象 我有两个从web服务代理生成的实体,所以我不能更改父类或实现接口或类似的东西。但我知道这两个对象具有相同的公共属性。Jon Skeet和Marc Gravell有一个名为的库。在MiscUtil.Reflection中有一个名为PropertyCopy的类,它完全按照您所描述的做。它只适用于.NET3.5 它的工作原理是运行S

有人建议使用一个好的实用程序类将值从一个对象映射到另一个对象吗?我想要一个实用程序类,它使用反射并获取两个对象,如果存在同名的公共属性,则将值从第一个对象复制到第二个对象


我有两个从web服务代理生成的实体,所以我不能更改父类或实现接口或类似的东西。但我知道这两个对象具有相同的公共属性。

Jon Skeet和Marc Gravell有一个名为的库。在
MiscUtil.Reflection
中有一个名为
PropertyCopy
的类,它完全按照您所描述的做。它只适用于.NET3.5

它的工作原理是运行SourceType的公共属性,将它们按名称与TargetType的公共属性进行匹配,确保每个属性都可以从源分配到目标,然后为这两种类型创建并缓存一个复制器函数(因此您不必每次都进行此反射)。我已经在生产代码中使用过它,可以证明它的优点

嘿,我想我应该发布他们的简明代码(不到100行,带注释)。可以找到此代码的许可证:

使用系统;
使用System.Collections.Generic;
使用System.Linq.Expressions;
运用系统反思;
命名空间MiscUtil.Reflection
{
/// 
///从源复制到其目标类型的泛型类
///复制方法中指定的类型。已指定类型
///分别利用泛型上的类型推断
///方法参数。
/// 
公共静态类属性复制,其中TTarget:class,new()
{
/// 
///将所有可读属性从源复制到新实例
///当然是目标。
/// 
公共静态TTarget CopyFrom(TSource-source),其中TSource:class
{
返回属性copier.Copy(来源);
}
/// 
///静态类来有效地存储可以
///进行复制。我们需要做一些工作来确保例外情况是正确的
///适当地传播,因为异常是在类型初始化时生成的
///时间,但我们希望它作为一个异常抛出。
/// 
私有静态类属性copier,其中TSource:class
{
专用静态只读功能复印机;
私有静态只读异常初始化异常;
内部静态目标拷贝(TSource源)
{
if(initializationException!=null)
{
抛出初始化异常;
}
if(source==null)
{
抛出新的ArgumentNullException(“源”);
}
返回复印机(源);
}
静态属性copier()
{
尝试
{
复印机=构建复印机();
initializationException=null;
}
捕获(例外e)
{
复印机=空;
初始化异常=e;
}
}
专用静态Func BuildCopier()
{
ParameterExpression sourceParameter=Expression.Parameter(typeof(TSource),“source”);
var bindings=newlist();
foreach(PropertyInfo sourceProperty in typeof(TSource).GetProperties())
{
如果(!sourceProperty.CanRead)
{
继续;
}
PropertyInfo targetProperty=typeof(TTarget).GetProperty(sourceProperty.Name);
if(targetProperty==null)
{
抛出新ArgumentException(“属性”+sourceProperty.Name+”不存在并且在“+typeof(TTarget.FullName)”中不可访问;
}
如果(!targetProperty.CanWrite)
{
抛出新ArgumentException(“属性”+sourceProperty.Name+”不能在“+typeof(TTarget.FullName)”中写入;
}
如果(!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
{
抛出新ArgumentException(“属性”+sourceProperty.Name+”在“+typeof(TTarget.FullName)”中具有不兼容的类型;
}
添加(Expression.Bind(targetProperty,Expression.Property(sourceParameter,sourceProperty));
}
表达式初始值设定项=Expression.MemberInit(Expression.New(typeof(TTarget)),绑定;
返回表达式.Lambda(初始值设定项,sourceParameter).Compile();
}
}
}
}

组合起来应该很简单

public static void CopyPropertyValues(object source, object destination)
{
    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;
            }
        }
    }
}
我们用这个。它运行得非常好。

我在读了马克·格雷威尔的文章后不久就在博客上写了这篇文章


它看起来(基于另一个答案)可能类似于Jon Skeet和Marc的MiscUtil中的答案。

我改进了Robinson的答案,并将其重构为对象类型的扩展方法,非常方便:

    public static void CopyPropertyValues( this object destination, object source )
    {
        if ( !( destination.GetType ().Equals ( source.GetType () ) ) )
            throw new ArgumentException ( "Type mismatch" );
        if ( destination 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.CopyPropertyValues ( src_enumerator.Current );
        }
        else
        {
            var destProperties = destination.GetType ().GetRuntimeProperties ();
            foreach ( var sourceProperty in source.GetType ().GetRuntimeProperties () )
            {
                foreach ( var destProperty in destProperties )
                {
                    if ( destProperty.Name == sourceProperty.Name 
                        && destProperty.PropertyType.GetTypeInfo ()
                            .IsAssignableFrom ( sourceProperty.PropertyType.GetTypeInfo () ) )
                    {
                        destProperty.SetValue ( destination, sourceProperty.GetValue (
                            source, new object[] { } ), new object[] { } );
                        break;
                    }
                }
            }
        }
    }

用Json.net做这件事怎么样

static T CopyPropertiesJson<T>(object source)
{
    string jsonsource = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(jsonsource);
}
static T CopyPropertiesJson(对象源)
{
字符串jsonsource=JsonConvert.SerializeObject(源);
返回JsonConvert.DeserializeObject(jsonsource);
}

Bugger。我花了很长时间才记住这是“汽车制造商”而不是“汽车地图”。顺便说一句,在谷歌上搜索“自动映射”很糟糕。有趣的是,有人喜欢一个基于
表达式
的代码来比较对象属性,我被邀请写这篇文章。我可能错了,但可能是这个:。@jitbit修复了URL@Marc格雷威尔:就像我
static T CopyPropertiesJson<T>(object source)
{
    string jsonsource = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(jsonsource);
}