Ответ: нет, это не дженерики.
Обработчики событий, зарегистрированные с использованием WeakEventManager
, запускаются только в том случае, если source
, указанное при регистрации, совпадает с тем, которое использовалось для вызова события, то есть оно должно вызываться (из source
) использование InternalEvent.Invoke(**this**, args)
.
Одним из следствий этого является то, что отправитель всегда будет экземпляром закрытого внутреннего класса, который практически бесполезен для любого потребляющего кода.
Для моей окончательной реализации ниже Я добавил перегрузку Subscribe(Action<TEventArgs> action)
, чтобы поддерживать чистоту кода, если это возможно. (Метод возвращает EventHandler<TEventArgs>
, который может использоваться для вызова Unsubscribe
, если требуется.)
РЕДАКТИРОВАТЬ: При использовании перегрузки Action
, если ссылка на возвращено EventHandler
не сохраняется, сборщик мусора - рано или поздно - соберет регистрацию, и действие сработает, как и ожидалось.
Еще одна вещь, которую следует учитывать, - это то, что событие может быть инициировано / вызвано из любого кода используя public void Invoke
, но я все равно часто нуждаюсь в этом методе и реализую его.
Я считаю этот код намного более простым и простым в использовании, чем "нативная" реализация WeakEventManager
- и, что самое важное он предотвращает утечку памяти из-за использования кода +=
для прослушивания события.
public class WeakEvent<TEventArgs> where TEventArgs : EventArgs
{
private class WeakEventInternal
{
public event EventHandler<TEventArgs> InternalEvent;
public void Invoke(TEventArgs args) => InternalEvent?.Invoke(this, args);
}
private readonly WeakEventInternal _internal= new WeakEventInternal();
public void Subscribe(EventHandler<TEventArgs> handler) => WeakEventManager<WeakEventInternal, TEventArgs>.AddHandler(_internal, nameof(WeakEventInternal.InternalEvent), handler);
public void Unsubscribe(EventHandler<TEventArgs> handler) => WeakEventManager<WeakEventInternal, TEventArgs>.RemoveHandler(_internal, nameof(WeakEventInternal.InternalEvent), handler);
public EventHandler<TEventArgs> Subscribe(Action<TEventArgs> handler)
{
EventHandler<TEventArgs> internalHandler = (object s, TEventArgs ee) => handler(ee);
WeakEventManager<WeakEventInternal, TEventArgs>.AddHandler(_internal, nameof(WeakEventInternal.InternalEvent), internalHandler);
return internalHandler;
}
public void Invoke(TEventArgs args) => _internal.Invoke(args);
}