2015-08-13 299 views
3

在C#中,如果我有一個擁有集合的對象,是否有可能檢索到包含集合的對象?如何獲取集合的父對象?

下面是一個例子:

public class TestObject 
{ 
    public string name { get; set; } 
    public TestObjectCollection testObjects{ get; set; } 
} 

TestObjectCollection收集從CollectionBase繼承,是TestObjects的集合。

下面是一個示例實現:

  • TestObject與的"Test1"
  • TestObject"Test1"名稱具有TestObjectCollectionTestObject"Test2"
的名稱的名稱創建

如果我有名爲"Test2"TestObject,我可以得到TestObject"Test1"

感謝

回答

2

做到這一點的唯一方法名稱是保持子對象的父級的引用。

this.testObjects = new TestObjectCollection(this); 

然後在TestObjectCollection的構造函數:

public TestObject ParentObject { get; set; } 

public TestObjectCollection(TestObject parent) 
{ 
    ParentObject = parent; 
    ... 
} 
+0

許多定義良好的多級對象(就像DataSets DataTables)正式爲你做了這個,就像上面的解決方案一樣。關鍵的一點是,它是正式定義的,而不是一種黑客,你可能會通過保留一個從未預料到的引用而以某種奇怪的方式摧毀父母對象鏈清理例程。例如,DataRow允許訪問其DataTable。 –

+0

只是好奇:「正式定義」和「黑客」有什麼區別? – Yogesh

+0

如果你必須在.Net中經歷非同尋常的長度,那麼這是一個破解。如果你正在引用一個已經存在的屬性(比如上面的解決方案),那麼它不是黑客。如果你不得不在4.0或4.5中使用反射來做某件事,那就是一種破解。 –

0

也許你可以做這樣的:

using System; 
using System.Collections.Generic; 

public class TestObject 
{ 
    private TestObjectCollection _testObjects; 

    public string name { get; set; } 
    public TestObjectCollection parentCollection { get; set; } 
    public TestObjectCollection testObjects 
    { 
     get 
     { 
      return _testObjects; 
     } 
     set 
     { 
      _testObjects = value; 
      _testObjects.parent = this; 
     } 
    } 
} 

public class TestObjectCollection 
{ 
    private List<TestObject> _testObjects; 

    public TestObject parent { get; set; } 

    public TestObjectCollection() 
    { 
     _testObjects = new List<TestObject>(); 
    } 

    public void Add(TestObject testObject) 
    { 
     testObject.parentCollection = this; 
     _testObjects.Add(testObject); 
    } 

    public TestObject this[int i] { 
     get { 
      return _testObjects[i]; 
     } 
    } 
} 


public class Test 
{ 
    public static void Main() 
    { 
     // your code goes here 
     TestObject test1 = new TestObject(); 

     TestObject test2 = new TestObject(); 

     var collection = new TestObjectCollection(); 
     collection.Add(test2); 
     test1.testObjects = collection; 

     if (test2.parentCollection.parent == test1) 
     { 
      Console.WriteLine("Done"); 
     } 
     else 
     { 
      Console.WriteLine("Fail"); 
     } 
    } 
} 

我使用的列表作爲例子,而創建子對象,你可以這樣做。

0

除非你明確的代碼,親子關係(如約傑什的答案),有沒有辦法找到「」父 - 很大一部分原因是可以有不止一個這樣的家長:

public class TestObject 
{ 
    public string name { get; set; } 
    public TestObjectCollection testObjects{ get; set; } 
} 
public class TestObjectCollection : CollectionBase 
{ 
    public void Add(TestObject to) 
    { 
     this.List.Add(to); 
    } 
} 
void Main() 
{ 
    TestObjectCollection children = new TestObjectCollection(); 
    TestObject child = new TestObject { name = "child" }; 
    children.Add(child); 

    TestObject parent = new TestObject { name = "parent", testObjects = children }; 
    TestObject otherParent = new TestObject { name = "otherParent", testObjects = children }; 
    TestObject stepParent = new TestObject { name = "stepParent", testObjects = children }; 
    TestObject inLocoParentis = new TestObject { name = "inLocoParentis", testObjects = children }; 
    // and we can keep going on and on and on ... 
} 
0

如果您不想在構造函數中傳遞引用,則可以使用靜態字典來跟蹤TestObject實例,並讓TestObjectCollection以延遲加載方式從該靜態字典中查找它的父項。

例如

public class TestObject 
{ 
    /// <summary> 
    /// Keep a list of all the instances of TestObject's that are created. 
    /// </summary> 
    internal static Dictionary<Guid, TestObject> _collections = new Dictionary<Guid, TestObject>(); 

    /// <summary> 
    /// An ID to uniquely identify an instance of a TestObject 
    /// </summary> 
    public Guid ID { get; private set; } 

    /// <summary> 
    /// A reference to the collection which will be set in the constructor 
    /// </summary> 
    public TestObjectCollection TestObjects { get; private set; } 

    public TestObject() 
    { 
     //generate the unique id 
     this.ID = Guid.NewGuid(); 
     this.TestObjects = new TestObjectCollection(); 
     //add this testobject to the List of test objects. 
     _collections.Add(this.ID, this); 
    } 

    /// <summary> 
    /// Destructor, kill the TestObject from the list of TestObject's. 
    /// </summary> 
    ~TestObject() 
    { 
     if (_collections.ContainsKey(this.ID)) 
     { 
      _collections.Remove(this.ID); 
     } 
    } 
} 

public class TestObjectCollection : IEnumerable<TestObject> 
{ 
    private List<TestObject> _testObjects = new List<TestObject>(); 

    public Guid ID { get; private set; } 

    public TestObject this[int i] 
    { 
     get 
     { 
      return _testObjects[i]; 
     } 
    } 

    private TestObject _Parent = null; 
    public TestObject Parent 
    { 
     get 
     { 
      if (_Parent == null) 
      { 
       _Parent = TestObject._collections.Values.Where(p => p.TestObjects.ID == this.ID).FirstOrDefault(); 
      } 
      return _Parent; 
     } 
    } 

    public TestObjectCollection() 
    { 
     this.ID = Guid.NewGuid(); 
    } 

    public void Add(TestObject newObject) 
    { 
     if (newObject != null) 
      _testObjects.Add(newObject); 
    } 

    public IEnumerator<TestObject> GetEnumerator() 
    { 
     return _testObjects.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return _testObjects.GetEnumerator(); 
    } 
} 

測試...

class Program 
{ 
    static void Main(string[] args) 
    { 
     TestObject tObject = new TestObject(); 
     Console.WriteLine("TestObject ID: " + tObject.ID); 
     Console.WriteLine("TestObject TestObjectCollection ID: " + tObject.TestObjects.ID); 
     Console.WriteLine("TestObject TestObjectCollection Parent ID: " + tObject.TestObjects.Parent.ID); 
     Console.WriteLine("Press any key..."); 

     Console.ReadKey(true); 
    } 
} 

那麼這樣做是在的TestObject的構造函數中給它的本身就是一個GUID ID。然後它創建一個TestObjectCollection的Instace。

在TestObjectCollection的構造函數中,它給自己一個GUID ID。

回到TestObject的構造函數中,它將Set的TestObject設置爲它剛剛創建的集合,然後將一個引用自身添加到靜態的TestObjects字典中。它使用TestObject的ID作爲所述字典的關鍵字。

然後在TestObjectCollection中,通過在該靜態字典中使用一個屬性來查找它的父集合,該屬性在調用之前不會自行設置它(因爲您無法在構造函數中確定它,因爲TestObject構造函數沒有添加引用)。

private TestObject _Parent = null; 
    public TestObject Parent 
    { 
     get 
     { 
      if (_Parent == null) 
      { 
       _Parent = TestObject._collections.Values.Where(p => p.TestObjects.ID == this.ID).FirstOrDefault(); 
      } 
      return _Parent; 
     } 
    } 
+0

通過允許在TestObject.TestObjects上設置一個延遲加載模式(如TestObjectCollection.Parent上的Parent屬性),然後從TestObject的構造函數中移除TestObjectCollection實例化,可以更新此模型以支持序列化。 –

+0

此外,即使將TestObject對象添加到TestObject.TestObjects集合仍然可以工作。因此,_Collections基本上是一個所有TestObject的平面列表,它們的子代和父代代碼都不在其中。 –