I spent some time learning how "Event Sourcing" works and how one would implement that in C# and i got stuck at some point. As it is very difficult to describe my problem without code I'll first give you a simplified version of my code. I removed all the unneeded code and left the relevant parts.
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)
}
}
What I would like to do is to prevent the base method to be used if a matching method is not implemented i. e.
User u = new User();
u.ApplyEvent(new UserCreated());
should work and call the method in User (which it does) but
u.ApplyEvent(new UserDeleted());
should not call the base method but give an error at compile time.
I've seen different approaches which would give a runtime error or simply ignore the problem if a matching method is not implemented like
Simply override the method and check the type
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 } }
Use the dynamic operator
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 } }
I know I could do it in either one of mentioned ways but I'm more interested in whether what I'm thinking of is possible or not.