Как я могу получить родительский объект коллекции?

В 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 ...   
}
Другие вопросы по тегам