简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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