通过具有特殊约束的反射克隆对象

时间:2010-12-08 05:17:05

标签: c# reflection

假设具有此属性的对象

public int? Prop1 { get; set; }
public string Prop2 { get; set; }
public EntityCollection<X> Prop3 { get; set; }
public EntityCollection<Y> Prop4 { get; set; }
public EntityCollection<Z> Prop5 { get; set; }

我可以使用以下方法复制prop1prop2

    public static void SetProperties(PropertyInfo[] fromFields,
                                             object fromRecord,
                                             object toRecord)
    {
        PropertyInfo fromField;

        if (fromFields == null)
        {
            return;
        }

        foreach (PropertyInfo t in fromFields)
        {
            fromField = t;

            fromField.SetValue(toRecord,
                               fromField.GetValue(fromRecord, null),
                               null);
        }
    }

但我不知道如何将prop3prop4prop5分别复制到另一个对象

修改 我应该 Serialize对象!我做这项工作是因为我的对象有大数据,我可以通过这个技巧复制一些数据。

如果我说这个问题的原始来源,这很有趣!我使用EF作为ORM,并通过SilverlightWCF个客户端中使用数据对象。当我在List<Foo>中发送WCF时,会发送List<Foo>及其关系数据!客户死了!

2 个答案:

答案 0 :(得分:1)

我要做的是制作对象Serializable。然后,您可以在内存中序列化对象,并将其反序列化为新的克隆对象。

我有这两个功能:

    public static MemoryStream ToMemoryStream(object entity)
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter formatter = new BinaryFormatter();

        formatter.Serialize(ms, entity);
        return ms;
    }

    public static T FromMemoryStream<T>(Stream stream)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        stream.Position = 0;
        return (T)formatter.Deserialize(stream);
    }

你的班级就像这样

[Serializable]
public class MyClass 
{
    public int? Prop1 { get; set; }
    public string Prop2 { get; set; }
    public EntityCollection<X> Prop3 { get; set; }
    public EntityCollection<Y> Prop4 { get; set; }
    public EntityCollection<Z> Prop5 { get; set; }
}

您现在可以将类序列化为内存并从中创建一个克隆。

public MyClass Clone()
{
    var myclass = new MyClass();
    /* Do Some init */

    var ms = ToMemoryStream(myclass);

    var myNewObject = FromMemoryStream<MyClass>(ms);
    return myNewObject;
}

答案 1 :(得分:1)

您必须更换以下行

  fromField.SetValue(toRecord, 
                           fromField.GetValue(fromRecord, null), 
                           null);

使用这些陈述,

        if (typeof(IList).IsAssignableFrom(t.PropertyType))
        {
            IList fromList = fromField.GetValue(fromRecord, null);
            IList toList = fromField.GetValue(toRecord, null);
            foreach (var item in fromList)
                toList.Add(item);
        }
        else
        {
            fromField.SetValue(toRecord,
                               fromField.GetValue(fromRecord, null),
                               null);
        }

你必须将IList替换为某个合适的接口,可能是ICollection或其他可以与EntityCollection一起使用的接口,我没有测试任何东西,所以我刚发布了这个例子。