Как я могу получить родительский объект коллекции?
В C#, если у меня есть объект, который имеет коллекцию, возможно ли извлечь объект, который содержит коллекцию?
Вот пример:
public class TestObject
{
public string name { get; set; }
public TestObjectCollection testObjects{ get; set; }
}
TestObjectCollection
коллекция наследует от CollectionBase
и это коллекция TestObjects
,
Вот пример реализации:
TestObject
создается с именем"Test1"
TestObject
с именем"Test1"
имеетTestObjectCollection
сTestObject
с именем"Test2"
Если у меня есть TestObject
с именем "Test2"
как я могу получить TestObject
с именем "Test1"
Спасибо
4 ответа
Единственный способ сделать это - сохранить ссылку на родителя в дочернем объекте. Вы можете сделать это при создании дочернего объекта:
this.testObjects = new TestObjectCollection(this);
Затем в конструкторе TestObjectCollection:
public TestObject ParentObject { get; set; }
public TestObjectCollection(TestObject parent)
{
ParentObject = parent;
...
}
Может быть, вы можете сделать это так:
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");
}
}
}
Я использовал список в качестве примера.
Если вы не хотите передавать ссылки в конструкторах, вы можете использовать статический словарь для отслеживания экземпляров 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. Затем он создает Instace of TestObjectCollection.
В конструкторе TestObjectCollection он присваивает себе идентификатор GUID.
Вернувшись в конструктор TestObject, он устанавливает TestObjects для только что созданной коллекции, а затем добавляет ссылку на себя в словарь TestObjects, который является статическим. Он использует идентификатор TestObject в качестве ключа для указанного словаря.
Затем в 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;
}
}
Если вы явно не закодируете эти отношения родитель-потомок (как в ответе Йогеша), невозможно найти "родителя" - по большей части, потому что может быть более одного такого родителя:
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 ...
}