У меня есть следующий класс, который имеет одно публичное событие с именем LengthChanged
:
class Dimension
{
public int Length
{
get
{
return this.length;
}
set
{
if (this.length != value)
{
this.length = value;
this.OnLengthChanged ();
}
}
protected virtual void OnLengthChanged()
{
var handler = this.LengthChanged;
if (handler != null)
{
handler (this, System.EventArgs.Empty);
}
}
public event System.EventHandler LengthChanged;
private int length;
}
Я бы хотел иметь возможность регистрировать / отменять регистрацию обработчиков для этого события в методе с именем Observer
, который ничего не знает о классе Dimension
. Я придумал два сценария, ни один из которых действительно не удовлетворяет:
Определите интерфейс ILengthChanged
с событием LengthChanged
, затем убедитесь, что Dimension
реализует ILengthChanged
. Затем я должен предоставить одну реализацию метода Observer
для каждого интерфейса, который я определяю. Это никоим образом не достаточно общий. Я действительно хотел бы иметь возможность просто передать ссылку на событие System.EventHandler
.
Используйте System.Action<System.EventHandler>
обратные вызовы для регистрации и отмены регистрации обработчика событий в методе Observer
, вот так:
класс Foo
{
public void Observer (системный регистр действий,
System.Action отменить регистрацию)
{
зарегистрироваться (this.MyEventHandler);
// keep track of the unregister callback, so that we can unregister
// our event handler later on, if needed...
}
private void MyEventHandler(object sender, System.EventArgs e)
{
...
}
}
, который затем будет вызываться так:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x);
и который при выполнении действительно завершит передачу события LengthChanged
внутренним обработчиком события MyEventHandler
. Но это не очень элегантно. Мне бы хотелось иметь возможность написать это вместо:
Foo foo = ...;
Dimension dim = ...;
foo.Observer (dim.LengthChanged);
но я понятия не имею, как этого можно достичь. Может быть, я упускаю что-то действительно очевидное здесь? Я предполагаю, что некоторая магия dynamic
могла бы каким-то образом добиться цели, но это не привело бы к проверке типов во время компиляции: я не хочу, чтобы пользователи Observer
передавали ссылки на события, которые не удовлетворяют System.EventHandler
подпись события.