将对象属性复制到另一个

时间:2014-02-27 14:06:48

标签: c# asp.net visual-studio-2010 reflection

我正在使用此方法将一个对象的属性复制到另一个对象并且其工作正常。 但今天我发现它不适用于不同对象的数组。

请帮助我。

public static class CopyClass
{
    /// <summary>
    /// Copies source object properties to target object properties.
    /// </summary>
    /// <param name="source">The source.</param>
    /// <param name="target">The target.</param>
    public static void CopyTo(object source, object target)
    {
        foreach (PropertyInfo propSource in source.GetType().GetProperties())
        {
            foreach (PropertyInfo propTarget in target.GetType().GetProperties())
            {
                if (propTarget.Name != propSource.Name) continue;
                (propTarget.GetSetMethod()).Invoke(target,
                    new object[] { propSource.GetGetMethod().Invoke(source, null) });
            }
        }
    }
}

3 个答案:

答案 0 :(得分:0)

你能看看这个功能吗?我不确定这是否适用于Arrays,但它确实适用于普通成员。

 public static object ObjectCopyProperties(this object sourceObject, object targetObject)
    {
        if (sourceObject == null || targetObject == null)
            return null;

        var targetInstance = targetObject;
        PropertyInfo newProp;
        foreach (PropertyInfo prop in sourceObject.GetType().GetProperties())
        {
            if (prop.CanRead)
            {
                newProp = targetInstance.GetType().GetProperty(prop.Name);
                if (newProp != null && newProp.CanWrite)
                {
                    newProp.SetValue(targetInstance, prop.GetValue(sourceObject, null), null);
                }
            }
        }
        return targetInstance;
    }

答案 1 :(得分:0)

鉴于以下2个类

public class UserType1
{
    public DateTime Created { get; set; }
    public string First { get; set; }
    public Gender Genter { get; set; }
    public int Id { get; set; }
    public string Last { get; set; }
    public DateTime Updated { get; set; }
    public string DontMatchType { get; set; }
    public string Unique1 { get; set; }
}

public class UserType2
{
    public DateTime Created { get; set; }
    public string First { get; set; }
    public Gender Genter { get; set; }
    public int Id { get; set; }
    public string Last { get; set; }
    public DateTime Updated { get; set; }
    public int DontMatchType { get; set; }
    public string Unique2 { get; set; }
}

和以下代码

    UserType1 user1 = new UserType1
        {
            Id = 1,
            First = "John",
            Last = "Doe",
            Genter = Gender.Male,
            Created = DateTime.Now.AddDays(-1),
            Updated = DateTime.Now,
            DontMatchType = "won't map",
            Unique1 = "foobar"
        };
    UserType2 user2 = CopyTo<UserType2>(user1);

你可以看到这个映射函数只会映射匹配的名称/类型

public static T CopyTo<T>(object source)
    where T : new()
{
    if (source == null) throw new ArgumentException("surce is null", "source");
    T target = new T();

    source.GetType()
          .GetProperties()
          .Join(target.GetType().GetProperties()
                , s => s.Name
                , t => t.Name
                , (s, t) => new
                    {
                        source = s,
                        target = t
                    })
          .AsParallel()
          .Where(inCommon => inCommon.source.PropertyType == inCommon.target.PropertyType
                             && inCommon.source.CanRead && inCommon.target.CanWrite)
          .ForAll(inCommon => inCommon.target.SetValue(target, inCommon.source.GetValue(source, null), null));
    return target;
}

你可以使用

public static IEnumerable<T> CopyTo<T>(IEnumerable<object> source)
    where T : new()
{
    return source.AsParallel().Select(CopyTo<T>);
}

复制像这样的集合

    UserType1[] users1 = new[]
        {
            new UserType1
                {
                    ...
                }
        };
    UserType2[] users2 = CopyTo<UserType2>(users1).ToArray();

这具有额外的好处,它不会为对象A中的每个属性不必要地循环对象B的所有属性,因为它使用连接来共同查找属性(按名称和类型)。

映射可能很棘手。您可以进入很多名称/类型和嵌套的情况。我建议将Automapper作为jjchiw提到。

答案 2 :(得分:0)

如果你的对象是可序列化的,你可以创建一个扩展方法来序列化源对象并反序列化它

public static class CloneExtensions
{
    public static T Clone<T>(this T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

        if(source == default(T))
            return default(T);

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}