У меня есть следующий класс, который имеет один публичное мероприятие под названием LengthChanged
:Как ссылаться на события в C#
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;
}
Я хотел бы иметь возможность регистрировать/UNREGISTER обработчики для этого события в методе, называемом Observer
, который ничего не знает о классе Dimension
. Я пришел с двумя сценариями, ни один из которых на самом деле удовлетворение:
Определить интерфейс
ILengthChanged
сLengthChanged
случае, убедитесь, чтоDimension
реализуетILengthChanged
. Затем я должен предоставить одну реализацию методаObserver
для каждого определяемого интерфейса. Это никоим образом не является достаточно общим. Я бы действительно хотел просто передать ссылку на событиеSystem.EventHandler
.Используйте
System.Action<System.EventHandler>
обратные вызовы для регистрации и отмены регистрации обработчика событий в методеObserver
, просто так:класс Foo { общественных недействительного Observer (System.Action регистр, 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
.
Если такие люди, как Эрик Мейера не смогли придумать более чистых решений, я подозревают, что нет другого способа сделать это. Это грустно ... Спасибо за ваш быстрый ответ, Джон. –