Я потратил некоторое время на изучение того, как работает «Event Sourcing» и как его реализовать в C #, и я застрял в какой-то момент.
Поскольку описать мою проблему без кода очень сложно, я сначала дам вам упрощенную версию моего кода. Я удалил весь ненужный код и оставил соответствующие части.
public interface IEvent { }
public class UserCreated : IEvent { }
public class UserDeleted : IEvent { }
public interface IEventSourcable
{
ICollection<IEvent> History { get; }
void ApplyEvent(IEvent e);
}
public abstract class EntityBase : IEventSourcable
{
public ICollection<IEvent> History { get; }
public void ApplyEvent(IEvent e)
{
History.Add(e);
}
}
public class User : EntityBase
{
public void ApplyEvent(UserCreated e)
{
base.ApplyEvent(e)
}
}
Что я хотел бы сделать, это запретить использование базового метода, если метод сопоставления не реализован, т.е. е.
User u = new User();
u.ApplyEvent(new UserCreated());
должен работать и вызывать метод в User (что он делает), но
u.ApplyEvent(new UserDeleted());
не должен вызывать базовый метод, но выдавать ошибку во время компиляции.
Я видел разные подходы, которые приводили бы к ошибке времени выполнения или просто игнорировали проблему, если не реализован метод сопоставления, такой как
Просто переопределите метод и проверьте тип
public class User : EntityBase
{
public override void ApplyEvent(IEvent e)
{
if (e is UserCreated)
ApplyEvent((UserCreated)e);
else if (e is UserDeleted)
ApplyEvent((UserDeleted)e);
else
throw new UnknownEventException(); // Or handle it however
}
}
Использование динамического оператора
public abstract class EntityBase : IEventSourcable
{
public ICollection<IEvent> History { get; }
public void ApplyEvent(IEvent e)
{
History.Add(e);
((dynamic)this).Apply((dynamic)e);
}
}
public class User : EntityBase
{
public override void Apply(UserCreated e)
{
// do something
}
}
Я знаю, что мог бы сделать это любым из упомянутых способов, но меня больше интересует, возможно ли то, о чем я думаю, или нет.