Мое понимание и мое видение этого предмета заключается в следующем:
Пакет по признакам - это вертикальная нарезка (структурирование исходного кода в соответствии с концепциями предметной области) вместо горизонтальной наслоения (структурирование в соответствии с техническими концепциями) .
Но говорить «вместо» не совсем верно, так как есть момент, когда вы должны различать эти технические концепции. Было бы лучше сначала сказать «пакет за объектом», а затем пакет за слоем внутри каждого объекта.
В стратегическом DDD каждый ограниченный контекст (BC) представляет собой вертикальный срез (целое приложение, полный стек ... с пользовательским интерфейсом, приложением, моделью предметной области и уровнями инфраструктуры).
Затем, внутри BC, тактический DDD способствует упаковке кода модели предметной области сначала в бизнес-концепции, а затем в технические концепции (тактические модели). Итак, у вас есть модули (группы агрегатов, которые тесно связаны и слабо связаны), и внутри каждого агрегата у вас есть сущности, объекты стоимости, фабрики, хранилище. Другие уровни (пользовательский интерфейс, приложение, инфраструктура) также могут быть структурированы по модулям.
Таким образом, в качестве резюме DDD следует смешанному подходу:
Упаковка с помощью бизнес-концепций с различными уровнями детализации: BC, модули, агрегаты.
Пакет за слоем внутри BC: пользовательский интерфейс, приложение, домен, инфраструктура.
PD: этот предмет (структура исходного кода) объясняется в главе 9 (Модули) книги Вона Вернона «Реализация DDD».
Существует метод FindControl, но не рекурсивный, если я помню правильно. Также Вы не гарантированы, что все иерархии управления существуют на page_init, ожидают сезам page_load прежде, чем получить доступ к средствам управления. Init для создания их.
Вы могли передать ссылку родителя ребенку и выставить метод на родителе для установки маркировки, хотя это очень сильно свяжет объекты. Иначе Вы могли выставить свойство на ребенке, что родитель мог затем проверить и установить свою собственную маркировку.
Существует несколько различных путей, которыми Вы могли пойти..., нужно было бы добавить свойство Parent к Вашему Дочернему классу... и затем сделать:
// in the context of parent's loading of child:
child.ParentObject = self;
Я уверен, что кто-то возвратится и скажет, что это нарушает некоторую лучшую практику или другого..., но пожатие плеч. Вы могли использовать события также, если бы Вы хотели поддержать некоторое разделение.
Если Ваше создание UserControl с помощью кода, почему бы не передать в родителе со строгим контролем типов конструктору.
public class MyUserControl1 : UserControl
{
public void Init(...)
{
var uc2 = new MyUserControl2(this);
}
}
public class MyUserControl2 : UserControl
{
private MyUserControl1 parentUserControl;
public MyUserControl2(MyUserControl1 parent)
{
this.parentUserControl = parent;
}
}
Теперь это сильно связывается и могло вызвать, Вы выходите позже, но для этого сценария это могло работать.
Вы лучший выбор состоит в том, чтобы ожидать до page_load, завершаетесь, и затем рекурсивно ищите на Page. Средства управления.
Вот некоторые дополнительные методы, которые помогут Вам accompish что:
var control = Page.GetControl(MyControlID);
public static class ControlExtensions
{
public static IEnumerable<Control> Flatten(this ControlCollection controls)
{
List<Control> list = new List<Control>();
controls.Traverse(c => list.Add(c));
return list;
}
public static IEnumerable<Control> Flatten(this ControlCollection controls, Func<Control, bool> predicate)
{
List<Control> list = new List<Control>();
controls.Traverse(c => { if (predicate(c)) list.Add(c); });
return list;
}
public static void Traverse(this ControlCollection controls, Action<Control> action)
{
foreach (Control control in controls)
{
action(control);
if (control.HasControls())
{
control.Controls.Traverse(action);
}
}
}
public static Control GetControl(this Control control, string id)
{
return control.Controls.Flatten(c => c.ID == id).SingleOrDefault();
}
public static IEnumerable<Control> GetControls(this Control control)
{
return control.Controls.Flatten();
}
public static IEnumerable<Control> GetControls(this Control control, Func<Control, bool> predicate)
{
return control.Controls.Flatten(predicate);
}
}
Или вы можете перебирать родительские элементы, пока не найдете желаемый элемент управления, например, с помощью метода расширения.
public static Control GetParentOfType(this Control childControl,
Type parentType)
{
Control parent = childControl.Parent;
while(parent.GetType() != parentType)
{
parent = parent.Parent;
}
if(parent.GetType() == parentType)
return parent;
throw new Exception("No control of expected type was found");
}
Подробнее об этом методе здесь: http://www.teebot.be/2009/08/extension-method-to-get-controls-parent.html