2011-06-21 70 views
1

我想擁有一個具有原始類型的對象的所有屬性,並且如果該對象與另一個類有關係,我想擁有另一個類的基本屬性如何獲取對象的所有基元類型

問題是如果實體A有實體B和B有A,我能做什麼

在簡單的情況下通過使用反射我可以得到第一級原始屬性,但是,我不能進入實體B,並再次獲得原始屬性A,一個循環將被創建,你提供什麼?

public class A 
{ 
public string Name{get;set;} 
public B B{get;set;} 
} 


public class B 
{ 
public string Category{get;set;} 
public A A{get;set;} 
} 
+2

請定義* primitive *? System.String是你的基本類型嗎?其他人會是什麼? –

+0

我只想要簡單的系統類型:byte,bool,string,int,datetime – Adrakadabra

+0

'System.IO.Stream'對我來說也是一個系統類型。它是BCL的一部分。根據你對原始的定義,它被認爲是原始的嗎?我試圖用我的問題來解釋你的問題是,在嘗試解決問題之前,您需要先定義**問題以及您正在尋找解決方案的確切方案。 –

回答

5

你可以繼續訪問類型的賽道,以免發生遞歸:

public class A 
{ 
    public string Name { get; set; } 
    public B B { get; set; } 
} 

public class B 
{ 
    public string Category { get; set; } 
    public A A { get; set; } 
} 

class Program 
{ 
    static void Main() 
    { 
     var result = Visit(typeof(A)); 
     foreach (var item in result) 
     { 
      Console.WriteLine(item.Name); 
     } 
    } 

    public static IEnumerable<PropertyInfo> Visit(Type t) 
    { 
     var visitedTypes = new HashSet<Type>(); 
     var result = new List<PropertyInfo>(); 
     InternalVisit(t, visitedTypes, result); 
     return result; 
    } 

    private void InternalVisit(Type t, HashSet<Type> visitedTypes, IList<PropertyInfo> result) 
    { 
     if (visitedTypes.Contains(t)) 
     { 
      return; 
     } 

     if (!IsPrimitive(t)) 
     { 
      visitedTypes.Add(t); 
      foreach (var property in t.GetProperties()) 
      { 
       if (IsPrimitive(property.PropertyType)) 
       { 
        result.Add(property); 
       } 
       InternalVisit(property.PropertyType, visitedTypes, result); 
      } 
     } 
    } 

    private static bool IsPrimitive(Type t) 
    { 
     // TODO: put any type here that you consider as primitive as I didn't 
     // quite understand what your definition of primitive type is 
     return new[] { 
      typeof(string), 
      typeof(char), 
      typeof(byte), 
      typeof(sbyte), 
      typeof(ushort), 
      typeof(short), 
      typeof(uint), 
      typeof(int), 
      typeof(ulong), 
      typeof(long), 
      typeof(float), 
      typeof(double), 
      typeof(decimal), 
      typeof(DateTime), 
     }.Contains(t); 
    } 
} 
+0

它正是我想要的,但問題是當A有兩個B,名稱B1和B2,我需要兩個B的屬性,它不會工作 – Adrakadabra

+0

@Adrakadabra,但因爲它是相同的類型,這意味着它有你已經擁有的相同屬性。所以你想要他們雙重或什麼? –

+0

是的,我希望他們在雙,iamgin一類人,這與hs2類關係countrySubDivision,一個爲BirthPlace,另一個爲leavingPlace,這個countrySubDivition有一個標題,我想這兩個標題 – Adrakadabra

0

我在工作中等待構建無聊,有你的功課樂趣;)

namespace Scratchpad 
{ 
    public static class TypeExtractor 
    { 
     public static IEnumerable<Type> ExtractTypes(this Type owner, HashSet<Type> visited = null) 
     { 
      if (visited == null) 
       visited = new HashSet<Type>(); 

      if (visited.Contains(owner)) 
       return new Type[0]; 

      visited.Add(owner); 

      switch (Type.GetTypeCode(owner)) 
      { 
       case TypeCode.Object: 
        break; 
       case TypeCode.Empty: 
        return new Type[0]; 
       default: 
        return new[] {owner}; 
      } 

      return 
       owner.GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | 
           BindingFlags.Static | 
           BindingFlags.FlattenHierarchy) 
        .SelectMany(x => x.ExtractTypes(visited)).Union(new[] {owner}).Distinct(); 
     } 

     public static IEnumerable<Type> ExtractTypes(this MemberInfo member, HashSet<Type> visited) 
     { 
      switch (member.MemberType) 
      { 
       case MemberTypes.Property: 
        return ((PropertyInfo) member).PropertyType.ExtractTypes(visited); 
        break; 
       case MemberTypes.Field: 
        return ((FieldInfo) member).FieldType.ExtractTypes(visited); 
       default: 
        return new Type[0]; 
      } 
     } 
    } 

    public class A 
    { 
     public string Name { get; set; } 
     public B B { get; set; } 
    } 


    public class B 
    { 
     public string Category { get; set; } 
     public A A { get; set; } 
    } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      var q = typeof (A).ExtractTypes(); 
      foreach (var type in q) 
      { 
       Console.Out.WriteLine(type.Name); 
      } 
     } 
    } 
} 
+0

做建設需要這麼長時間你有時間做家庭作業:-)我可能會試圖優化我的編譯時間:-) –

+1

我將採取我們以前的建設工程師撬棍:) –

0

我會做如下:

void Traverse(Type type, ISet<Type> marks, ICollection<PropertyInfo> result) 
    { 
     if (marks.Contains(type)) return; else marks.Add(type); 
     foreach (var propertyInfo in type.GetProperties()) 
      if (propertyInfo.PropertyType.IsPrimitive) result.Add(propertyInfo); 
      else Traverse(propertyInfo.PropertyType, marks, result); 
    } 

var props = new List<PropertyInfo>(); 
Traverse(yourRootType, new HashSet<Type>(), props); 
0

你需要跟蹤你已經檢查過的類型。

public static List<PropertyInfo> ProcessType(Type type) 
{ 
    return ProcessType(type, new List<Type>()); 
} 
public static List<PropertyInfo> ProcessType(Type type, List<Type> processedTypes) 
{ 
    // Keep track of results 
    var result = new List<PropertyInfo>(); 

    // Iterate properties of the type 
    foreach (var property in type.GetProperties()) 
    { 
     var propertyType = property.PropertyType; 

     // If the property has a primitive type 
     if (propertyType.IsPrimitive) 
     { 
      // add it to the results 
      result.Add(property); 
     } 
     // If the property has a non-primitive type 
     // and it has not been processed yet 
     else if (!processedTypes.Contains(propertyType)) 
     { 
      // Mark the property's type as already processed 
      processedTypes.Add(propertyType); 

      // Recursively processproperties of the property's type 
      result.AddRange(ProcessType(propertyType, processedTypes)); 
     } 
    } 

    return result; 
} 
相關問題