C#使用PropertyInfo填充对象

时间:2014-08-02 16:59:45

标签: c# recursion generic-collections propertyinfo generic-function

我有以下课程:

用户

public partial class User
{
    public long iduser { get; set; }
    public string email { get; set; }
    public string name { get; set; }
    public System.DateTime birthdate { get; set; }
    public string about { get; set; }
    public bool active { get; set; }
    public System.DateTime created_date { get; set; }
    public System.DateTime last_update { get; set; }
    public string password { get; set; }
    public string image { get; set; }
    public string username { get; set; }
    public virtual ICollection<Interest> Interests { get; set; }
}

兴趣

public partial class Interest
{

    public long idinterest { get; set; }
    public string name { get; set; }
    public bool active { get; set; }
    public System.DateTime last_update { get; set; }
    public System.DateTime created_date { get; set; }
    public string css_class { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

WSReturnUserGetById

public class WSReturnUserGetById
{
    public long iduser { get; set; }
    public string email { get; set; }
    public string name { get; set; }
    public System.DateTime birthdate { get; set; }
    public string about { get; set; }
    public List<WSReturnInterestGetById> Interests { get; set; }
}

和WSReturnInterestBetById

public class WSReturnInterestGetById
{
    public long idinterest { get; set; }
    public string name { get; set; }
    public string css_class { get; set; }
}

我使用以下代码填充WSReturnUserGetById和User上的数据:

public T PopulateObjects<T>(object obj) where T : class, new()
{
    if (obj == null) return null;
    T Obj = new T();
    PropertyInfo[] properties = obj.GetType().GetProperties();
    foreach (PropertyInfo p in properties)
    {
        PropertyInfo objPf = typeof(T).GetProperty(p.Name);
        if (objPf != null)
        {
            if (p.PropertyType == objPf.PropertyType)
            {
                objPf.SetValue(Obj, p.GetValue(obj));
            }
        }
    }
    return Obj;
}

我还有一个功能可以填充对象列表

public List PopulateObjectList(IEnumerable objects)其中T:class,new()     {

    List<T> response = new List<T>();
    foreach (U obj in objects)
    {
        T Obj = new T();
        if (obj != null)
        {
            PropertyInfo[] properties = obj.GetType().GetProperties();
            foreach (PropertyInfo p in properties)
            {
                PropertyInfo objPf = typeof(T).GetProperty(p.Name);
                if (objPf != null)
                {
                    if (p.PropertyType == objPf.PropertyType)
                    {
                        objPf.SetValue(Obj, p.GetValue(obj));
                    }
                }
            }
        }
        response.Add(Obj);
    }

    return response;
}

当我使用该代码时,它的作用除了属性&#34;兴趣&#34;在User和WSReturnUserGetById中,&#39; couse的类型不同。所以,我试图调整,并使用此功能使其工作:

public object populateCompleteObj<T, U>(U mainobj) where T : class, new()
{
    if (mainobj.GetType().IsGenericType && mainobj is IEnumerable)
    {
        List<T> response = new List<T>();
        foreach (object obj in (IEnumerable)mainobj)
        {
            T Obj = new T();
            if (obj != null)
            {
                PropertyInfo[] properties = obj.GetType().GetProperties();
                foreach (PropertyInfo p in properties)
                {
                    PropertyInfo objPf = typeof(T).GetProperty(p.Name);
                    if (objPf != null)
                    {
                        if (typeof(IEnumerable).IsAssignableFrom(objPf.PropertyType))
                        {
                            objPf.SetValue(Obj, populateCompleteObj<'objpf property class', 'obj property class'>(p.GetValue(obj)));
                        }
                        else if (p.PropertyType == objPf.PropertyType)
                        {
                            objPf.SetValue(Obj, p.GetValue(obj));
                        }
                    }
                }
            }
        }

    }
    else
    {
        if (mainobj == null) return null;
        T Obj = new T();
        PropertyInfo[] properties = mainobj.GetType().GetProperties();
        foreach (PropertyInfo p in properties)
        {
            PropertyInfo objPf = typeof(T).GetProperty(p.Name);
            if (objPf != null)
            {
                if (p.PropertyType == objPf.PropertyType)
                {
                    objPf.SetValue(Obj, p.GetValue(mainobj));
                }
            }
        }
        return Obj;
    }

}

问题是我不知道如何获取属性信息的类,所以可以进行递归。有谁知道怎么做?

2 个答案:

答案 0 :(得分:1)

根据我的理解,您希望以递归方式调用populateCompletedObj<T,U>。这可以轻松完成,但我会先建议一些更改。

    我不需要
  • U,我会从通用定义中删除它,而只是使用object
  • populateCompletedObj包裹在自己的对象中(如果尚未包含)

让方法以递归方式调用,然后看起来像这样:

// this.GetType is the class that contains the method to call
var recurseMethod = this.GetType().GetMethod("populateCompletedObj").MakeGenericMethod(objPf.PropertyType);

然后您可以这样调用此方法:

// Invoke the method on the current instance with the property
recurseMethod.Invoke(this, new object[1] {p.GetValue(obj) });

毕竟我最终得到了这个:

public TDest ReflectionCopy<TDest>(object srcVal)
    where TDest : class, new()
{
    if (srcVal == null) { return null; }
    TDest dest = new TDest();
    var props = srcVal.GetType().GetProperties();
    foreach (PropertyInfo p in props)
    {
        PropertyInfo objPf = typeof(TDest).GetProperty(p.Name);
        if (objPf != null)
        {
            if (objPf.PropertyType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(objPf.PropertyType))
            {
                var destCollType = objPf.PropertyType.GenericTypeArguments[0];
                var recurse = this.GetType().GetMethod("ReflectionCopy").MakeGenericMethod(destCollType);
                IEnumerable srcList = (IEnumerable)p.GetValue(srcVal);
                IList destlst = (IList)Activator.CreateInstance(objPf.PropertyType);
                foreach(var srcListVal in srcList)
                {
                    var destLstVal = recurse.Invoke(this, new object[1] { srcListVal });
                    destlst.Add(destLstVal);
                }
                objPf.SetValue(dest, destlst);
                continue;
            }

            if (p.PropertyType == objPf.PropertyType)
            {
                objPf.SetValue(dest, p.GetValue(srcVal));
            }
        }
    }
    return dest;
}

总而言之,你可以从一种类型序列化,并使用类似JSON.net的方式反序列化到另一种类型,并避免所有这些痛苦。

public TDest SerializeCopy<TDest>(object srcVal)
    where TDest : class, new()
{
    if (srcVal == null) { return null; }
    var temp = JsonConvert.SerializeObject(srcVal);
    return JsonConvert.DeserializeObject<TDest>(temp);
}

以下是所有代码的要点:

https://gist.github.com/garystanford/36932d38a785272ee907

答案 1 :(得分:0)

如果我理解你的意思,那么你正在寻找一种获得通用内在类型的方法。

string中的List<string>

您可以使用以下代码实现此目的:

PropertyInfo objPf = typeof(T).GetProperty(p.Name);
var type = pi.PropertyType.GetGenericArguments()[0];