简体   繁体   English

C#反射与泛型

[英]C# Reflection & Generics

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. 给定下面的代码,您将如何实现该伪函数,以便在给定Parent实例的情况下,将枚举类型Properties来查找具有与Parent类型相同的Property的子对象,并将引用设置为所提供的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. 运行此命令后,子Pet实例中的每个Person将成为Parent实例。

 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);
                    }
                }
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM