Все достижения, которые накопал в данном направлении заключаются в следующем:
public class Объект
{
public string Название;
public List<Помещение> Помещения;
public Объект(string Название)
{
this.Название=Название;
Помещение Помещение_1= new Помещение("Помещение_1");
Помещения.Add (Помещение_1);
}
}
public class Помещение
{
public string Название;
public List<Окно> Окна;
public Помещение(string Название)
{
this.Название=Название;
Окно Окно_1= new Окно("Помещение_1");
Окна.Add (Окно_1);
}
}
public class Окно
{
public string Название;
public Окно(string Название)
{
this.Название=Название;
}
}
Таким образом я могу обращаться к элементам класса через поиск:
Проект ТекущийПроект = new Проект("Проект_1");
string Название = ТекущийПроект.Помещения.Find("Помещение").Окна.Find("Окно");
Как мне доработать код, чтобы я мог обращаться к ним, как в примере сверху? Хватит хотя бы названия технологии.
_>Здравствуйте!
_>Есть задача — реализовать на c# вложенную структуру классов, типа:
_>Дом(Дом_1).Квартира(Квартира_1).Комната(Комната_1).Дверь.Открыть();
_>Все достижения, которые накопал в данном направлении заключаются в следующем:
_>
_> public class Объект
_> {
_> public string Название;
_> public List<Помещение> Помещения;
_> public Объект(string Название)
_> {
_> this.Название=Название;
_> Помещение Помещение_1= new Помещение("Помещение_1");
_> Помещения.Add (Помещение_1);
_> }
_> }
_> public class Помещение
_> {
_> public string Название;
_> public List<Окно> Окна;
_> public Помещение(string Название)
_> {
_> this.Название=Название;
_> Окно Окно_1= new Окно("Помещение_1");
_> Окна.Add (Окно_1);
_> }
_> }
_> public class Окно
_> {
_> public string Название;
_> public Окно(string Название)
_> {
_> this.Название=Название;
_> }
_> }
_>
_>Таким образом я могу обращаться к элементам класса через поиск:
Скрытый текст
_>
_>Проект ТекущийПроект = new Проект("Проект_1");
_>string Название = ТекущийПроект.Помещения.Find("Помещение").Окна.Find("Окно");
_>
_>Как мне доработать код, чтобы я мог обращаться к ним, как в примере сверху? Хватит хотя бы названия технологии.
public class Помещение
{
public string Название;
public Dictionary<String, Окно> Окна = new Dictionary<String, Окно>();
public Помещение(string Название)
{
this.Название=Название;
Окно Окно_1= new Окно("Окно_1");
Окна.Add("Окно_1", Окно_1);
}
}
string Название = ТекущийПроект.Помещения["Помещение_1"].Окна["Окно_1"].Название;
Стараемся не оверквотить или хотябы под спойлер прятать. H_D.
R>Класс корень имеет статический метод Дом, принимающий строку и возвращающий квартиру итд, только методы становятся не статические.
А разве статический класс может иметь не статические методы? А даже если и может, то не буду же я создавать для каждого случая свой метод, нужны какие-то элементы типа List
Здравствуйте, Alex Lakers, Вы писали:
_>>Как мне доработать код, чтобы я мог обращаться к ним, как в примере сверху? Хватит хотя бы названия технологии.
AL>Попробуйте поискать по "Fluent Builder".
Это не оно, таким я не могу создавать вложенные структуры.
Здравствуйте, wolf_larsen, Вы писали:
_>Здравствуйте!
_>Есть задача — реализовать на c# вложенную структуру классов, типа:
_>Дом(Дом_1).Квартира(Квартира_1).Комната(Комната_1).Дверь.Открыть();
здесь видимо подразумевается что
Дом — абстракция
Дом_1 — конкретная реализация ...
Может такое подойдет (на примере 2 классов, но суть должны понять):
class Door
{
public string Title { get; set; }
}
class Room
{
public string Title { get; set; }
public Door this[string index]
{
get { return this._doors.Find(r => string.Equals(r.Title, index)); }
}
private readonly List<Door> _doors = new List<Door>();
}
class House
{
public string Title { get; set; }
public Room this[string index]
{
get { return this._rooms.Find(r => string.Equals(r.Title, index)); }
}
private readonly List<Room> _rooms = new List<Room>();
}
тогда
var house = new House();
var door = house["my_room"]["my_door"];
Правда необходимо учитывать вероятность появления NullReferenceException при неправильных именах.
Кроме того, что-то мне подсказывает что надо смотреть на задачу шире. И вам тут может пригодиться шаблон Компоновщик (Composite).
Здравствуйте, Doc, Вы писали: Doc>Здравствуйте, wolf_larsen, Вы писали:
Скрытый текст
Doc>Может такое подойдет (на примере 2 классов, но суть должны понять):
Doc>
Doc> class Door
Doc> {
Doc> public string Title { get; set; }
Doc> }
Doc> class Room
Doc> {
Doc> public string Title { get; set; }
Doc> public Door this[string index]
Doc> {
Doc> get { return this._doors.Find(r => string.Equals(r.Title, index)); }
Doc> }
Doc> private readonly List<Door> _doors = new List<Door>();
Doc> }
Doc> class House
Doc> {
Doc> public string Title { get; set; }
Doc> public Room this[string index]
Doc> {
Doc> get { return this._rooms.Find(r => string.Equals(r.Title, index)); }
Doc> }
Doc> private readonly List<Room> _rooms = new List<Room>();
Doc> }
Doc>
Doc>тогда
Doc>
Doc>var house = new House();
Doc>var door = house["my_room"]["my_door"];
Doc>
Doc>Правда необходимо учитывать вероятность появления NullReferenceException при неправильных именах.
Doc>Кроме того, что-то мне подсказывает что надо смотреть на задачу шире. И вам тут может пригодиться шаблон Компоновщик (Composite).
Данные конструкции в целом отражают суть того, что надо, однако есть следующая проблема: У всех вложенных классов будут одни и теже методы в intellysence. Как я могу сделать так, чтобы при погружении в структуру мне на выбор давались те элементы, которые касаются не только данного уровня, но и данной конкретной сущности?
Здравствуйте, wolf_larsen, Вы писали:
_>Как я могу сделать так, чтобы при погружении в структуру мне на выбор давались те элементы, которые касаются не только данного уровня, но и данной конкретной сущности?
Где и как вы собираетесь это использовать?
Здравствуйте, wolf_larsen, Вы писали:
_>Данные конструкции в целом отражают суть того, что надо, однако есть следующая проблема: У всех вложенных классов будут одни и теже методы в intellysence.
В этом и суть Компоновщика. Однотипная работа с различными элементами. Итоговый элемент можно уже привести (при крайней необходимости) к определенному типу.
_>Как я могу сделать так, чтобы при погружении в структуру мне на выбор давались те элементы, которые касаются не только данного уровня, но и данной конкретной сущности?
Например приведением типов.
Но опять же, надо шире смотреть на задачу. Я все это к тому, что возможно ваша исходная версия структуры (в первом сообщении) не является оптимальной. Исходить тут надо от абстракий и того, что чего они нужны.
Здравствуйте, wolf_larsen, Вы писали:
_>Здравствуйте, Doc, Вы писали:
_>Данные конструкции в целом отражают суть того, что надо, однако есть следующая проблема: У всех вложенных классов будут одни и теже методы в intellysence. Как я могу сделать так, чтобы при погружении в структуру мне на выбор давались те элементы, которые касаются не только данного уровня, но и данной конкретной сущности?
В стартовом посте все у вас было нормально для этого. По различным именам вы обращались к различным типизированным коллекциям вложенных сущностей (не классов). Единственное чего не хватало — метода Find(string).
Можно объявить свои коллекции, например так:
public class СписокПомещений : List<Помещение>
{
public Помещение Find(string name) { return this.Where(x => x.Название == name).FirstOrDefault(); };
}
И далее использовать эти коллекции вместо List<Помещение> и т.п.
Проблему дублирования описаний вспомогательных коллекций можно решить с помощью выделения поля Название в базовый класс
class NamedItem { public string Название; }
public class NamedItemList<TNamedItem> : List<TNamedItem>
where TNamedItem : NamedItem
{
public TNamedItem Find(string name) { return this.Where(x => x.Название == name).FirstOrDefault(); };
}
или передав способ извлечения имени в конструктор соответствующего списка:
public class ItemList<TItem> : List<TItem>
{
public ItemList(Func<TItem, string> getNameFunc) { _getNameFunc = getNameFunc; }
private Func<TItem, string> _getNameFunc;
public TNamedItem Find(string name) { return this.Where(x => _getNameFunc(x) == name).FirstOrDefault(); };
}
Но как уже упомянул Doc, использование такой конструкции будет сопряжено с риском NullReferenceException. Можно и с этим побороться.
static class MyExtensions
{
public static Помещение Помещение(this Проект obj, string name)
{
if (obj == null)
return null;
return obj.Помещения.Where(x => x.Название == name).FirstOrDefault();
}
}
тогда
Проект ТекущийПроект = new Проект("Проект_1");
Окно окно = ТекущийПроект.Помещение("Помещение").Окно("Окно");
if (окно != null)
окно.Open();
На любом этапе может появиться null, но он не страшен вплоть до вызова метода Open у окна. Но и с этим можно что-то сделать:
static class MyExtensions
{
...
public static void DoIfNotNull<T>(this T obj, Action<T> action)
{
if (obj != null)
action(obj);
}
}
Проект ТекущийПроект = new Проект("Проект_1");
ТекущийПроект.Помещение("Помещение").Окно("Окно").DoIfNotNull(x => x.Open());
Но с этим путем появляется другая проблема. После выполнения выражения нельзя быть уверенным что окно было найдено и метод Open вызвался. Так что вопросы, о том как это будет использовано, не праздные.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, wolf_larsen, Вы писали:
_>>Здравствуйте, Doc, Вы писали:
_>>Данные конструкции в целом отражают суть того, что надо, однако есть следующая проблема: У всех вложенных классов будут одни и теже методы в intellysence. Как я могу сделать так, чтобы при погружении в структуру мне на выбор давались те элементы, которые касаются не только данного уровня, но и данной конкретной сущности?
S>В стартовом посте все у вас было нормально для этого. По различным именам вы обращались к различным типизированным коллекциям вложенных сущностей (не классов). Единственное чего не хватало — метода Find(string).
S>Можно объявить свои коллекции, например так: S>
S>И далее использовать эти коллекции вместо List<Помещение> и т.п.
S>Проблему дублирования описаний вспомогательных коллекций можно решить с помощью выделения поля Название в базовый класс
S>
S>class NamedItem { public string Название; }
S>public class NamedItemList<TNamedItem> : List<TNamedItem>
S> where TNamedItem : NamedItem
S>{
S> public TNamedItem Find(string name) { return this.Where(x => x.Название == name).FirstOrDefault(); };
S>}
S>
S>или передав способ извлечения имени в конструктор соответствующего списка: S>
S>На любом этапе может появиться null, но он не страшен вплоть до вызова метода Open у окна. Но и с этим можно что-то сделать: S>
S>static class MyExtensions
S>{
S> ...
S> public static void DoIfNotNull<T>(this T obj, Action<T> action)
S> {
S> if (obj != null)
S> action(obj);
S> }
S>}
S>Проект ТекущийПроект = new Проект("Проект_1");
S>ТекущийПроект.Помещение("Помещение").Окно("Окно").DoIfNotNull(x => x.Open());
S>
S>Но с этим путем появляется другая проблема. После выполнения выражения нельзя быть уверенным что окно было найдено и метод Open вызвался. Так что вопросы, о том как это будет использовано, не праздные.
Смоделированы трехмерные помещения. Идея следующая: создать объектную модель помещения, чтобы к любому элементу помещения можно было бы обратиться способом "от общего к частному" и получить на выходе методы присущие только данному устройству — дверь(методы — открыть, закрыть), шкаф(методы — цвет, типдерева), лампа(методы — включить, получитьяркость).
Суть идеи — удобное логическое обращение с разнородными объектами принадлежащими помещению.
Изначально я вообще хотел использовать чисто статические класса объектов, но т.к. помещений может быть очень много, то это будет очень геморно поддерживать.
Здравствуйте, wolf_larsen, Вы писали:
_>Смоделированы трехмерные помещения. Идея следующая: создать объектную модель помещения, чтобы к любому элементу помещения можно было бы обратиться способом "от общего к частному" и получить на выходе методы присущие только данному устройству — дверь(методы — открыть, закрыть), шкаф(методы — цвет, типдерева), лампа(методы — включить, получитьяркость).
либо, если очень хочется статики в compile-time, берете вашу модель, T4 и генерируете по модели с помощью T4 классы, отражающие специфику каждого конкретного объекта:
building.A1.Bathroom.MainDoor.Open();
В первом случае нет статической проверки на этапе компиляции, и вы узнаете о том, что в помещении нет такой комнаты в рантайме. Но при этом изменение исходной модели вам пофиг.
Во втором случае статическая проверка есть, но при изменении модели вам необходимо повторно сгенерировать код классов.
Здравствуйте, wolf_larsen, Вы писали:
_>Здравствуйте, samius, Вы писали:
_>Смоделированы трехмерные помещения. Идея следующая: создать объектную модель помещения, чтобы к любому элементу помещения можно было бы обратиться способом "от общего к частному" и получить на выходе методы присущие только данному устройству — дверь(методы — открыть, закрыть), шкаф(методы — цвет, типдерева), лампа(методы — включить, получитьяркость). _>Суть идеи — удобное логическое обращение с разнородными объектами принадлежащими помещению.
Удобное для кого? Кто будет имена предметов вводить? Пользователь? Программист?
_>Изначально я вообще хотел использовать чисто статические класса объектов, но т.к. помещений может быть очень много, то это будет очень геморно поддерживать.
Здравствуйте, wolf_larsen, Вы писали:
_>Смоделированы трехмерные помещения. Идея следующая: создать объектную модель помещения, чтобы к любому элементу помещения можно было бы обратиться способом "от общего к частному"
Повторюсь — берите Компоновщик.
_>и получить на выходе методы присущие только данному устройству — дверь(методы — открыть, закрыть), шкаф(методы — цвет, типдерева), лампа(методы — включить, получитьяркость).
В определенный момент приводить к заданному типу. Т.е. все объекты получат общий интерфейс для работы с ними (перебор, поиск, добавление, удаление и т.д.), но при необходимости можно обратиться и как конкретному типу.
Здравствуйте, Doc, Вы писали:
Doc>Повторюсь — берите Компоновщик.
_>>и получить на выходе методы присущие только данному устройству — дверь(методы — открыть, закрыть), шкаф(методы — цвет, типдерева), лампа(методы — включить, получитьяркость).
Doc>В определенный момент приводить к заданному типу. Т.е. все объекты получат общий интерфейс для работы с ними (перебор, поиск, добавление, удаление и т.д.), но при необходимости можно обратиться и как конкретному типу.
Поискал примеры компоновщика — да, действительно он позволяет создать виртуальную структуру, однако я не нашел примера, как мне обратиться к конкретному члену данной структуры и получить его конкретные методы. Все что описано — как добавить элемент в структуру и как удалить.
Здравствуйте, wolf_larsen, Вы писали:
_>Поискал примеры компоновщика — да, действительно он позволяет создать виртуальную структуру, однако я не нашел примера,
Выше я давал ссылку на пример реализации данного шаблона.
_>как мне обратиться к конкретному члену данной структуры
Там есть поиск.
_>и получить его конкретные методы.