收录日期:2019/12/11 03:43:54 时间:2010-10-28 14:29:11 标签:c#,reflection,icollection

I have a method where I am passing in two object, which have the same property names, and I'm using Reflection to get the values from one object and set the values on the other. My problem is when I come across a property that is a collection, the original is EntityCollection and the one getting set is ObservableCollection, and I'm obviously going to throw a casting error when I try to set the value.

So how would I go about this? I thought one way would be to get the instance of the EntityCollection property and in a loop use Activator.CreateInstance() to add a new item to the ObservableCollection. But I come across another question of how to get the original instance.

I would be greatly appreciative for some insight into this dilemma. I'll post the code for the method that I'm working with. It currently doesn't work, mainly I posted it just for a reference. So please don't point out the obvious. Thanks in advance.

protected void SetValues(Object thisObject, Object entity)
{
    PropertyInfo[] properties = entity.GetType().GetProperties();
    foreach (PropertyInfo property in properties)
    {
        var value = property.GetValue(entity, null);
        var thisObjectsProperty = thisObject.GetType().GetProperty(property.Name);

        if (thisObjectsProperty != null && value != null)
        {
            if (thisObjectsProperty.PropertyType.GetInterface("ICollection", true) != null                && thisObjectsProperty.PropertyType.GetGenericArguments().Count() > 0)
            {
                Type genericType = thisObjectsProperty.PropertyType.GetGenericArguments()[0];
                Type entityCollectionType = property.PropertyType;
                Type thisCollectionType = thisObjectsProperty.PropertyType;

                IList entityCollection = (IList)Activator.CreateInstance(entityCollectionType.MakeGenericType(genericType));
                IList observableCollection = (IList)Activator.CreateInstance(thisCollectionType.MakeGenericType(genericType));

                foreach (var item in entityCollection)
                {
                    String typeString = String.Concat("RulesGenerator.DependencyObjects.", genericType.Name);
                    Type newItemType = Type.GetType(typeString, false, true);
                    if (newItemType != null)
                    {
                        var newItem = Activator.CreateInstance(newItemType);
                        SetValues(newItem, item);
                        observableCollection.Add(newItem);
                    }
                }
            }
            else
                thisObjectsProperty.SetValue(thisObject, value, null);
        }
    }
}

Implement the ICloneable interface to provide a deep copy. You should be able to find some examples, but here is a starting point:

http://msdn.microsoft.com/en-us/library/system.icloneable%28v=VS.71%29.aspx

http://en.csharp-online.net/ICloneable

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;


public class testMain : ICloneable
{

    private string m_TestProp;

    private List<Record> m_Items = new List<Record>();
    public string TestProp
    {
        get { return m_TestProp; }
        set { m_TestProp = value; }
    }

    public List<Record> Items
    {
        get { return m_Items; }
    }


    public object Clone()
    {

        testMain cpy =(testMain) this.MemberwiseClone();

        foreach (Record rec in this.Items)
        {
            Record recCpy = (Record)rec.Clone();
            cpy.Items.Add(recCpy);
        }

        return cpy;
    }

}

public class Record : ICloneable
{

    private string m_TestProp;

    public string TestProp
    {
        get { return m_TestProp; }
        set { m_TestProp = value; }
    }

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}