Если это кажется неправильным, потому что события являются более сложными и внешними, чем это необходимо для вашей внутренней коммуникации (что, я считаю, по крайней мере частично верно, учитывая, что события могут вызывать несколько клиентов, тогда как вы знаете, что вам нужно только уведомить одного, верно?) Тогда я предлагаю следующую альтернативу. Вместо использования событий для передачи завершения Foo в FooHandler, поскольку Foo в любом случае является внутренним, вы можете добавить параметр обратного вызова в конструктор или метод Load Foo, который Foo может вызывать после завершения загрузки. Этот параметр может быть просто функцией, если у вас есть только один обратный вызов, или это может быть интерфейс, если у вас их много. Вот как я думаю, ваш код будет выглядеть с упрощенным внутренним интерфейсом:
public delegate void FooLoaded(FooHandler sender, EventArgs e);
class Foo
{
Action<Foo> callback;
/* ... some code ... */
public void Load(Action<Foo> callback) { this.callback = callback; load_asynchronously(); }
public void callMeWhenLoadingIsDone() { callback(this); }
}
class FooHandler
{
public event FooLoaded OneFooLoaded;
/* ... some code ... */
public void LoadAllFoos()
{
foreach (Foo f in FooList)
{
f.Load(foo_loaded);
}
}
void foo_loaded(Foo foo)
{
// Create EventArgs based on values from foo if necessary
OneFooLoaded(this, null);
}
}
Обратите внимание, что это также позволяет печатать более строго с делегатом FooLoaded.
Если, с другой стороны, он чувствует себя неправильно, потому что событие не должно проходить через FooHandler, чтобы добраться до клиента, то 1) Я бы оспорил это, потому что, если клиент не хочет иметь дело с человеком Объекты Foo, они также не должны отнимать события от них на этом уровне, и 2) Если вы действительно хотите это сделать, вы можете реализовать некоторый публичный интерфейс обратного вызова на Foo, даже если Foo является закрытым, или использовать механизм, подобный предложенному Павлом. , Я думаю, однако, что клиентам нравится простота реализации меньшего числа обработчиков событий и различения источника внутри одного обработчика, а не необходимость подключать (и потенциально отключать) события от десятков меньших объектов.