C#反射&泛型 [英] C# Reflection & Generics

查看:128
本文介绍了C#反射&泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个复杂的反射问题。假设下面的代码将如何实现伪代码,以便给定一个Parent实例,它将枚举类型Properties查找具有与Parent相同类型的Property的子对象,并将引用设置为提供的p。希望这是有道理的。此外,我也需要这个来处理通用列表。请参阅下面的示例对象图。运行后,子Pet实例中的每个Person都将是Parent实例。

  public class ChildSetter< Parent> 
{
public void Set(Parent p)
{

// pseudo
// var parentName = p.GetType()。Name;
// foreach(p.Properties中的var属性)
// {
// if(!property.IsList)
// {
// if( property.ContainsProperty(parentName))
// property.Properties [parentName] = p;
//}
// else
// {
// if(property.ListType.ContainsProperty(parentName))
// {
/ / foreach(属性中的var项)
// {
// item.Properties [parentName] = p;
//}
//}
//}
//}
}
}

public class Person
{
public Pet Pet {get;组; }
public IList< Pet>宠物{get;组; }

}

public class Pet
{
public Person Person {get;组; }
}

此代码的非泛型示例如下所示:

  public void Set(Person p)
{
p.Pet.Person = p;
foreach(var pet in p.Pets)
{
pet.Person = p;
}
}


解决方案

I没有测试过,但怎么样:

  using System; 
使用System.Collections;
使用System.Collections.Generic;
使用System.Reflection;

静态类程序
{
static void Main()
{
...
}
public static void SetParent< (T).GetProperties
(BindingFlags.Public | BindingFlags.Instance))
{
(T)(T root)
{
foreach(PropertyInfo prop in typeof如果(!prop.CanRead)继续;

类型listType = null;
foreach(在prop.PropertyType.GetInterfaces()中输入interfaceType)
{
if(interfaceType.IsGenericType&&
interfaceType.GetGenericTypeDefinition()== typeof(IList< >))
{// IList< T>检测到
listType = interfaceType.GetGenericArguments()[0];
}
}

List< PropertyInfo> propsToSet =新列表< PropertyInfo>();
foreach(PropertyInfo childProp in(listType ?? prop.PropertyType).GetProperties(
BindingFlags.Public | BindingFlags.Instance))
{
if(childProp.PropertyType == typeof (T))propsToSet.Add(childProp);
}

if(propsToSet.Count == 0)continue; //没什么可做的
if(listType == null)
{
object child = prop.GetValue(root,null);
if(child == null)continue;
foreach(PropertyInfo childProp in propsToSet)
{
childProp.SetValue(child,root,null);
}
}
else
{
IList list =(IList)prop.GetValue(root,null);
foreach(列表中的对象子)
{
if(child == null)continue;
foreach(PropertyInfo childProp in propsToSet)
{
childProp.SetValue(child,root,null);
}
}
}
}
}
}


Got a complex reflection question. Given the code below how would you implement the pseudo so that given an instance of Parent it will enumerate over the types Properties find child objects with a Property of the same type as Parent and set the reference to the provided p. Hope that makes sense. Also I need this to work with Generic lists as well. See below for sample object graph. After running this every Person in the child Pet instances will be the Parent instance.

 public class ChildSetter<Parent>
    {
        public void Set(Parent p)
        {

            //pseudo 
            //var parentName = p.GetType().Name;
            //foreach (var property in p.Properties)
            //{
            //   if (!property.IsList)
            //   {
            //      if (property.ContainsProperty(parentName))
            //          property.Properties[parentName] = p;
            //   }
            //   else
            //   {
            //      if (property.ListType.ContainsProperty(parentName))
            //      {
            //          foreach (var item in property)
            //          {
            //              item.Properties[parentName] = p;
            //          }
            //      }
            //   }
            //}
        }
    }

public class Person
{
    public Pet Pet { get; set; }
    public IList<Pet> Pets { get; set; }

}

public class Pet
{
    public Person Person { get; set; }
}

A non generic example of this code is below:

 public void Set(Person p)
    {
        p.Pet.Person = p;
        foreach (var pet in p.Pets)
        {
            pet.Person = p;
        }
    }

解决方案

I haven't tested it, but how about:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

static class Program
{
    static void Main()
    {
        ...
    }
    public static void SetParent<T>(T root)
    {
        foreach (PropertyInfo prop in typeof(T).GetProperties
            (BindingFlags.Public | BindingFlags.Instance))
        {
            if (!prop.CanRead) continue;

            Type listType = null;
            foreach (Type interfaceType in prop.PropertyType.GetInterfaces())
            {
                if (interfaceType.IsGenericType &&
                    interfaceType.GetGenericTypeDefinition() == typeof(IList<>))
                { // IList<T> detected
                    listType = interfaceType.GetGenericArguments()[0];
                }
            }

            List<PropertyInfo> propsToSet = new List<PropertyInfo>();
            foreach (PropertyInfo childProp in (listType ?? prop.PropertyType).GetProperties(
                BindingFlags.Public | BindingFlags.Instance))
            {
                if (childProp.PropertyType == typeof(T)) propsToSet.Add(childProp);
            }

            if(propsToSet.Count == 0) continue; // nothing to do
            if (listType == null)
            {
                object child = prop.GetValue(root, null);
                if (child == null) continue;
                foreach (PropertyInfo childProp in propsToSet)
                {
                    childProp.SetValue(child, root, null);
                }
            }
            else
            {
                IList list = (IList)prop.GetValue(root, null);
                foreach (object child in list)
                {
                    if (child == null) continue;
                    foreach (PropertyInfo childProp in propsToSet)
                    {
                        childProp.SetValue(child, root, null);
                    }
                }
            }
        }
    }
}

这篇关于C#反射&amp;泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆