Я пытаюсь использовать Domain Events
, чтобы уведомить, когда что-то произошло в системе (заимствовано у here и here).Невозможно добавить объект в список
Я действительно близок к тому, что код работает так, как я хочу, однако, я ударил немного кирпичной стены. Вот мой DomainEvents
класс:
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T : IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback); // <---- Problem here, since I can't add callback to the collection.
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (var action in Actions)
{
if (action is IEventHandler<T>)
{
((IEventHandler<T>)action).Handle(args);
}
}
}
выше не будет компилироваться, так как Actions.Add
не может принять callback
, так как это IEventHandler<T>
типа, а затем IEventHandler<IDomainEvent>
типа. Вот еще один код для уточнения.
Это называется от моего консольного приложения:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler
реализует IEventHandler<CustomerHasUnpaidDuesEvent>
, где CustomerHasUnpaidDuesEvent
реализует IDomainEvent
.
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent @event)
{
this.EmailSender.SendEmail(@event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
Это то, что я не получаю - если CustomerHasUnpaidDuesEvent
реализует IDomainEvent
, то почему вызов Actions.Add
неудачу? Как я могу это решить?
EDIT:
Для того, чтобы прояснить ситуацию, вот весь код для моего тестового приложения:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "[email protected]";
c.CheckUnpaidDues();
}
}
public interface IEventHandler<in T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEmailSender
{
void SendEmail(string emailAddress);
}
public interface IDomainEvent
{
}
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T: IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (IEventHandler<T> action in Actions)
{
(action).Handle(args);
}
}
}
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent @event)
{
this.EmailSender.SendEmail(@event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public bool HasUnpaidDues { get; set; }
public void CheckUnpaidDues()
{
HasUnpaidDues = true;
DomainEvents.Raise(new CustomerHasUnpaidDuesEvent(this));
}
}
Приветствия. Jas.
[Это] (http://stackoverflow.com/questions/1259104/ilist-using-covariance-and-contravariance-in- c-is-this-possible) должна быть связанной проблемой. – Vlad
@ Vlad - Извините, что вам больно, но можете ли вы помочь мне с примером кода? Это «ковариация» и «контравариантность» для меня очень сбивает с толку. Как я могу изменить свой код, чтобы использовать эти методы для решения моей проблемы? –
Как объявляется 'IEventHandler'? Это системный интерфейс или ваш локальный? – Vlad