2009-02-16 47 views
0

有一個複雜的反射問題。假設下面的代碼將如何實現僞代碼,以便給定一個Parent實例,它將枚舉類型Properties查找具有與Parent相同類型的Property的子對象,並將引用設置爲提供的p。希望這是有道理的。此外,我還需要這個與通用列表一起工作。請參閱下面的示例對象圖。運行後,子Pet實例中的每個人都將是父實例。C#Reflection&Generics

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

這段代碼的非普通例子如下:

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

這個問題是涉及到這樣一個問題: http://stackoverflow.com/questions/552736/child-tables-in-nhibernate – bleevo 2009-02-16 09:59:37

回答

4

我沒有測試過,但如何:

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

謝謝馬克我會檢查出 – bleevo 2009-02-16 10:17:46