Почему объекты являются сиротами, если создатель - PullRequest
0 голосов
/ 03 августа 2011

Рассмотрим следующий код

    public class City
    {
        public string Name { get { return "New York"; } }

        Building empEstate;
        Building nyTimes;
        public void Init()
        {
            // I hate passing "this" to all object
            empEstate = new EmpEstate(this); 
            setSomeProperty(empEstate);
            // any one can create new object of some other city 
            // and pass to the building
            nyTimes = new NYTimes(this);
            ...
            other = new OtherBuildings(this)
        }

        public void PrintAddresses()
        {
            empEstate.Print();
            nyTimes.Print();
            ...
            other.Print();
        }
    }

    public abstract class Building {
        City _city;
        public Building(City city){
            this._city = city;
        }
        public abstract string Name { get;}
        public void Print(){
            Console.WriteLine(this.Name);
            Console.Write(",");
            Console.WriteLine(this._city.Name);
        }
    }
  1. Во-первых, я хочу лучшее решение для этого подхода.Печать это только пример.Фактически каждый строительный объект возбуждает какое-то событие для объекта City.Я не хочу добавлять обработчик в каждое здание, так как в городе может быть несколько зданий.Также я не хочу добавлять каждый из них в список, так как это две задачи для каждого здания (одна инициализация и вторая добавление в список, одну забывают добавить в список при написании нового здания).Для этого я хочу, чтобы вызывающая сторона была автоматически доступна вызываемой стороне, например свойство родительского элемента управления (хотя оно было добавлено в this.Controls)

  2. Используя память, мы можем знать, кто является родителемтекущего объекта.Как GC знает, что на объект не ссылаются (включая создателя).Разве мы не можем создать метод (безопасный или небезопасный), использующий память для идентификации объекта вызывающего.Я вижу, что мы можем использовать StackTrace, чтобы увидеть иерархию вызовов, можем ли мы перехватить здесь при создании нового объекта.

Ответы [ 4 ]

1 голос
/ 14 августа 2011

Строительный завод в городе решил мою проблему передачи этого каждому объекту

public interface ICity
    {
        string Name { get; }
    }
    public abstract class City : ICity
    {
        public T CreateBuilding<T>()
        {
            T buildingInstance = Activator.CreateInstance<T>();
            ((IBuilding)buildingInstance).SetCity(this);
            return buildingInstance;
        }

        public abstract string Name { get; }
    }

    interface IBuilding
    {
        ICity City { get; }
        void SetCity(ICity city);
    }
    public abstract class Building : IBuilding
    {
        private ICity _city;
        public ICity City { get { return _city; } }
        public void IBuilding.SetCity(ICity city)
        {
            this._city = city;
        }
        public abstract string Name { get; }
        public void Print()
        {
            Console.WriteLine(this.Name);
            Console.Write(",");
            Console.WriteLine(this._city.Name);
        }
    }
    public class EmpEstate : Building
    {
        public override string Name { get { return "Emp State"; } }
    }
    public class NYTimes : Building
    {
        public override string Name { get { return "NY Times"; } }
    }
    public class NewYorkCity : City
    {
        public override string Name { get { return "New York"; } }

        EmpEstate empEstate;
        NYTimes nyTimes;
        public void Init()
        {
            // Now I dont need to pass this
            empEstate = this.CreateBuilding<EmpEstate>();
             setSomeProperty(empEstate);
            // now any one cannot create building in new your and 
            // say it belongs to Philedelphia :)
            nyTimes = this.CreateBuilding<NYTimes>();
        }

        public void PrintAddresses()
        {
            empEstate.Print();
            nyTimes.Print();
        }
    }

Проблема заключалась в том, что уже было создано несколько классов, и для новой функциональности нам понадобился объект-создатель в базовом классе Building Object. Мы не хотели модифицировать конструктор каждого класса и передавать этот объект каждому. А класс City (в примере) был в основном кодом на стороне плагина, поэтому разрешение им передавать город (если разработчик плагина передает неправильный город) может нарушить функциональность всего приложения. Поэтому изменение базы плагинов решило мою задачу. Предложения приветствуются.

0 голосов
/ 03 августа 2011

Я думаю, вы неправильно используете термины родитель и создатель . Объект, создавший экземпляр, не имеет особых отношений с экземпляром (например, фабрики создают объекты, но не поддерживают ссылки на них), поэтому, как правило, нет способа узнать, кто или что создал конкретный экземпляр.
В том же смысле, parent не имеет значения для общего объекта. Мы можем как-то сделать вывод, что Форма является родительской для TextBox, но это не особые отношения. В этом случае это просто означает, что TextBox находится в коллекции Contols формы, а его Parent установлен в Form.

Вы правы, что это может привести к несоответствиям (Form1 считает, что TextBox - это дочерний элемент, но TextBox считает, что это Parent - это Form2), но я не знаю и не думаю, что есть лучшее решение. такого рода отношений, чем Children collection / Parent reference.

0 голосов
/ 03 августа 2011

Подберите несколько ваших вопросов:

Я ненавижу проходить это

Почему? Вы говорите зданию, к какому городу оно относится. Как еще ты мог это сделать. Я вижу это как общую идиому для соединения объектов.

Также я не хочу добавлять каждого из них в список, так как это две задачи для каждого здания (одна инициализация и вторая добавка в список, одна не забудьте добавить в список при написании нового здания).

Мне неясно, к какому списку вы хотите добавить их, но ваше беспокойство по поводу "забвения" будет преодолено, если вы выполните работу в конструкторе базы:

    public Building(City city){
        this._city = city;
        // add the building to the list here - nothing to "forget"
    }

Что касается GC, то как только создатель создал что-то, между ними не возникает никаких отношений, если только вы не решите сохранить ссылку. Вы сделали это с

empEstate = new EmpEstate(this); 

так что, пока Город не является кандидатом на сбор мусора, EmpState также не будет.

0 голосов
/ 03 августа 2011

Нет логического «владельца» объекта.Проверка трассировки стека ... обычно не идеальна.По сравнению с Parent, это не очень отличается от вашего существующего подхода - просто это устанавливается с помощью методов / свойств, а не в конструкторе.

Если city необходим только дляконтекст таких методов, как Print, почему бы не передать его в качестве параметра, например nyTimes.Print(this) и т. д. Если вам могут потребоваться другие значения, а не принимать множество параметров, рассмотрите возможность использования какого-либо объекта контекста, который имеет город - то есть

class PrintContext {
     public City City {get;private set;}
     // other stuff...
     public PrintContext(City city/*, other stuff...*/) {
          City = city;
     }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...