如果您不想在構造函數中傳遞引用,則可以使用靜態字典來跟蹤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;
}
}
許多定義良好的多級對象(就像DataSets DataTables)正式爲你做了這個,就像上面的解決方案一樣。關鍵的一點是,它是正式定義的,而不是一種黑客,你可能會通過保留一個從未預料到的引用而以某種奇怪的方式摧毀父母對象鏈清理例程。例如,DataRow允許訪問其DataTable。 –
只是好奇:「正式定義」和「黑客」有什麼區別? – Yogesh
如果你必須在.Net中經歷非同尋常的長度,那麼這是一個破解。如果你正在引用一個已經存在的屬性(比如上面的解決方案),那麼它不是黑客。如果你不得不在4.0或4.5中使用反射來做某件事,那就是一種破解。 –