Для этого варианта использования, я думаю, лучший подход - создать интерфейс IScenario
и позволить Scenario
расширить этот интерфейс. Это скроет детали реализации Scenario
и позволит вам передать IScenario
непосредственно в конструктор A
.
public interface IScenario
{
void Add(toBeUpdated obj);
void Update(int num);
}
, который вы теперь можете расширить Scenario
вроде так:
public class Scenario : IScenario
{
...
}
Обновите A
соответственно:
public class A : toBeUpdated
{
...
public A(int number, IScenario scenario)
{
B1 = new B(number);
scenario.Add(this);
scenario.Add(B1);
}
...
}
Как использовать будет что-то вроде:
var sce = new Scenario();
A a1 = new A(1, sce);
A a3 = new A(3, sce);
sce.Update(2);
sce.Update(5);
Этот подход гарантирует, что A
не знает Scenario
, что оно обновляется с минимальными усилиями, и вполне тестируемо. Другой подход заключается в добавлении метода к A
, который регистрирует a Scenario
(полезно, если A
необходимо добавить новый Scenario
после создания):
public void Register(IScenario scenario)
{
scenario.Add(this);
scenario.Add(B1);
}
Примечание: Создание IScenario
не требуется , но это хорошо, когда вы попадаете в unit testing
и хотите mock
объектов.
Редактировать: Вы всегда можете использовать отражение, чтобы получить все свойства типа toBeUpdated
из A
:
// In Scenario
public void Add(toBeUpdated obj)
{
UpdateEvent += obj.OnUpdate;
// Get all properties of type toBeUpdated
var properties = obj.GetType()
.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
.Select(x => x.GetValue(obj))
.OfType<toBeUpdated>();
foreach (var property in properties)
{
UpdateEvent += property.OnUpdate;
}
}