C# Is interface casting a violation of the Liskov Substitution Principle - c#

I would like to refer to the example that was used before on SO
with the Duck and Electric Duck:
public interface IDuck
{
void Swim();
}
public class Duck : IDuck
{
public void Swim()
{
//do something to swim
}
}
public class ElectricDuck : IDuck
{
public void Swim()
{
if (!IsTurnedOn)
return;
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
}
The original violation for LSP would look like this:
void MakeDuckSwim(IDuck duck)
{
if (duck is ElectricDuck)
((ElectricDuck)duck).TurnOn();
duck.Swim();
}
One solution by the author was to put the Logic inside the electric duck's swim method to turn itself on:
public class ElectricDuck : IDuck
{
public void Swim()
{
if (!IsTurnedOn)
TurnOn();
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
}
I have come across other scenarios where an extended interface can be created that supports some sort of initialization:
public interface IInitializeRequired
{
public void Init();
}
Electric Duck could then be extended with this interface:
public class ElectricDuck : IDuck, IInitializeRequired
{
public void Swim()
{
if (!IsTurnedOn)
return;
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
#region IInitializeRequired Members
public void Init()
{
TurnOn();
}
#endregion
}
EDIT: The reason for the extended interface Is based on the author saying that turning on automatically in the swim method might have other undesired results.
Then the method instead of checking and casting to a specific type can look for an extended interface instead:
void MakeDuckSwim2(IDuck duck)
{
var init = duck as IInitializeRequired;
if (init != null)
{
init.Init();
}
duck.Swim();
}
The fact that i made the initialization concept more abstract then to create an extended interface called IElectricDuck with TurnOn() method, may make this seem that I did the right thing, however the whole Init concept may only exist because of electric duck.
Is this a better way/solution or is this just an LSP violation in disguise.
Thanks

It's an LSP violation in disguise. Your method accepts an IDuck, but it requries verification of the dynamic type (whether the IDuck implements IInitializeRequired or not) to work.
One possibility to fix this would be to accept the fact that some ducks require initialization and redefine the interface:
public interface IDuck
{
void Init();
/// <summary>
/// Swims, if the duck has been initialized or does not require initialization.
/// </summary>
void Swim();
}
Another option is to accept that an uninitialized ElectricDuck is not really a duck; thus, it does not implement IDuck:
public class ElectricDuck
{
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
public IDuck GetIDuck()
{
if (!IsTurnedOn)
throw new InvalidOperationException();
return new InitializedElectricDuck(); // pass arguments to constructor if required
}
private class InitializedElectricDuck : IDuck
{
public void Swim()
{
// swim logic
}
}
}

I would still consider your final example as an LSP violation because logically you do exactly this. As you said, there is no concept of initialization really, it is just made up as a hack.
Indeed, your MakeDuckSwim method should not know anything about any duck's specifics (whether it should be initialized first, fed with some destination after initialization, etc).
It just has to make the provided duck swim!
It is hard to tell on this example (as it is not real), but looks like somewhere "upper" there is a factory or something that creates you a specific duck.
It it possible that you miss the concept of a factory here?
If there was one, then It should know what duck it is creating exactly so probably it should be responsible to know how to initialize a duck, and the rest of your code just works with IDuck without any "ifs" inside behavioral methods.
Obviously you can introduce the concept of "initialization" straight to IDuck interface. Say, a "normal" duck needs to be fed, an electrical one needs to be turned on, etc :) But it sounds a bit dodgy :)

I think first you need to answer this question about electric ducks - do they turn themselves on automatically when someone asks them to swim? If so, turn them on in the Swim method.
If not, it is the duck's client responsibility for turning it on, and you might as well just throw an InvalidOperationException if the duck can't swim because it's turned off.

public interface ISwimBehavior
{
void Swim();
}
public interface IDuck
{
void ISwimBehavior { get; set; }
}
public class Duck : IDuck
{
ISwimBehavior SwimBehavior { get { return new SwimBehavior(); }; set; }
}
public class ElectricDuck : IDuck
{
ISwimBehavior SwimBehavior { get { return new EletricSwimBehavior(); }; set; }
}
The behaviour classes:
public class SwimBehavior: ISwimBehavior
{
public void Swim()
{
//do something to swim
}
}
public class EletricSwimBehavior: ISwimBehavior
{
public void Swim()
{
if (!IsTurnedOn)
this.TurnOn();
//do something to swim
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
}

Maybe something like this:
public interface IDuck
{
bool CanSwim { get; }
void Swim();
}
public class Duck : IDuck
{
public void Swim()
{
//do something to swim
}
public bool CanSwim { get { return true; } }
}
public class ElectricDuck : IDuck
{
public void Swim()
{
//swim logic
}
public void TurnOn()
{
this.IsTurnedOn = true;
}
public bool IsTurnedOn { get; set; }
public bool CanSwim { get { return IsTurnedOn; } }
}
Client would be changed like:
void MakeDuckSwim(IDuck duck)
{
if (duck.CanSwim)
{
duck.Swim();
}
}

Related

How can I solve this Interface Segregation Principle Violation

I'm facing a similar scenario to this issue and I was wondering if it's possible to get around a cleaner solution.
Supposing we have a party that has People on it, We have the interface:
public interface IPerson {
void Arrive();
void Dance();
}
And its implementations, people that are able to dance
public class PersonThatCanDance : IPerson {
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
//Logic related to dancing
}
}
and those who aren't
public class PersonThatCannotDance : IPerson {
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
}
}
Knowing this, now we have the party with 2 people
public class Party {
private IPerson person1;
private IPerson person2
private void StartParty() {
person1.Arrive();
person2.Arrive();
}
private void StartMusic() {
person1.Dance();
person2.Dance();
}
}
With this scenario settled, the problem comes when we want to make the party not care if the person is a person that can dance or not. The party throws the people into dancing no matter if they have functionality to do so.
From what I understand, the existence of the Dance() method in PersonThatCannotDance is a violation of ISP but making the party not care about what kind of person is preventing me from respecting the principle.
Is there a way to get around this? Thank you.
yes you are right. it is violation of ISP.
public interface IArrive : IPerson {
void Arrive();
DateTime Time {get;set;}
string Mode {get;set;}
}
public interface IDance: IPerson {
void Dance();
DateTime duration {get;set;}
string Type {get;set;}
}
public interface IPerson {
string Name {get;set;}
void Dress();
}
Now Implementations looks like this, people that are able to dance
public class PersonThatCanDance : IArrive,IDance {
string Name {get; set;}
public void Dress() {
//Logic related to arriving
}
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
//Logic related to dancing
}
}
and those who aren't
public class PersonThatCannotDance : IArrive {
string Name {get; set;}
public void Dress() {
//Logic related to arriving
}
public void Arrive() {
//Logic related to arriving
}
}
In Party Class
public class Party {
private IPerson person1 = new PersonThatCanDance();
private IPerson person2 = new PersonThatCannotDance();
private void StartParty() {
((IArrive)person1).Arrive();
((IArrive)person2).Arrive();
}
private void StartMusic() {
if(person1 is IDance)
{
((IDance)person1).Dance();
}
if(person2 is IDance)
{
((IDance)person2).Dance();
}
}
}
Now I hope this solution will work. please let me know if still have doubt.
There is not enough information to determine the right design for your situation, but I can offer a design that's broadly applicable:
public interface IPerson {
void Arrive();
}
public class PersonThatCanDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
...
party.AddDancers(this);
}
public void Dance() {
//Logic related to dancing
...
}
}
public class PersonThatCannotDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
...
}
}
public class Party {
private IPerson person1;
private IPerson person2;
ArrayList dancers = new ArrayList();
private void StartParty() {
person1.Arrive(this);
person2.Arrive(this);
}
public void AddDancers(PersonThatCanDance dancer) {
dancers.Add(dancer);
}
private void StartMusic() {
for (var dancer in dancers) {
dancer.Dance();
}
}
}
A possibly more idiomatic alternative, is going by events.
public class PersonThatCanDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
...
party.OnCueMusic(this.Dance);
}
...
}
public class Party {
public delegate void Dance();
ArrayList musicEvents = new ArrayList();
...
public void OnCueMusic(Dance dance) {
musicEvents.Add(dance);
}
private void StartMusic() {
for (var musicEvent in musicEvents) {
musicEvent();
}
}
}

How to implement a factory pattern based on argument types?

I have PhotoBase class
public abstract class PhotoBase
{
public string Path { get; set; }
}
And I have multiple derived classes, for example the path may indicate a location in the file system or an external url.
public class FilePhoto : PhotoBase {}
public class ExternalPhoto : PhotoBase {}
I want to load these photos, I have a PhotoLoader class like below:
public class PhotoLoader
{
public void Load(FilePhoto Photo)
{
// get the photo from file system
}
public void Load(ExternalPhoto Photo)
{
// download the photo from path
}
}
Now I want to load these photos, so I have to do:
public class PhotoImporter
{
private PhotoLoader _photoLoader;
public PhotoImporter(PhotoLoader photoLoader)
{
_photoLoader = photoLoader;
}
public void ImportPhoto(PhotoBase photo)
{
if (photo is FilePhoto)
{
_photoLoader.Load(photo as FilePhoto);
}
if (photo is ExternalPhoto)
{
_photoLoader.Load(photo as ExternalPhoto);
}
}
}
I have several derived classes and I may add more photo types in the future. Is there a more elegant way that I could get rid of if conditions? Using factory pattern?
Another approach would be to have an abstract method Load on PhotoBase, that's then implemented by each subclass:
public abstract class PhotoBase
{
public string Path { get; set; }
public abstract void Load();
}
public class FilePhoto : PhotoBase
{
public override void Load()
{
// load from file system
}
}
public class ExternalPhoto : PhotoBase
{
public override void Load()
{
// load from path
}
}
That way, you can simply call the Load method on a PhotoBase:
public class PhotoImporter
{
public void ImportPhoto(PhotoBase photo)
{
photo.Load();
}
}
The main advantage is that each subclass implements the Load method, and therefore you can add as many subclasses as you want, without worrying about forgetting to implement it.
The main drawback to this implementation is that the Load methods can't depend on other dependencies. So for example, if one day you need to load a photo from a database, you can't pass the DBContext.
Proper to way to implement it which will make code easy to maintain is as follows:
public abstract class PhotoBase
{
public string Path { get; set; }
public abstract void Load(); // Have a abtract method
}
public class FilePhoto : PhotoBase {
public override void Load() { // Implement the abtract method
Console.WriteLine("FilePhoto");
}
}
public class ExternalPhoto : PhotoBase {
public override void Load() { // // Implement the abtract method
Console.WriteLine("ExternalPhoto");
}
}
public class PhotoLoader
{
private PhotoBase _PhotoBase;
public PhotoLoader(PhotoBase photoBase) { // Resolved by Dependency Injection
_PhotoBase = photoBase;
}
public void Load()
{
_PhotoBase.Load();
}
}
public class PhotoImporter
{
private PhotoLoader _photoLoader;
public PhotoImporter(PhotoLoader photoLoader) // Resolved by Dependency Injection
{
_photoLoader = photoLoader;
}
public void ImportPhoto()
{
_photoLoader.Load();
}
}
You need to have Dependency Injection define so that specified implementation will get resolved and appropriate 'Load' method will be invoked.
void Main()
{
// Following dependency should be resolved by Dependency Injection
PhotoBase filePhotoBase = new FilePhoto();
PhotoLoader filePhotoLoader = new PhotoLoader(filePhotoBase);
PhotoImporter filePhotoImporter = new PhotoImporter(filePhotoLoader);
PhotoBase externalPhotoBase = new ExternalPhoto();
PhotoLoader externalPhotoLoader = new PhotoLoader(externalPhotoBase);
PhotoImporter externalPhotoImporter = new PhotoImporter(externalPhotoLoader);
filePhotoImporter.ImportPhoto(); // Shows output 'FilePhoto'
externalPhotoImporter.ImportPhoto(); // Shows output 'ExternalPhoto'
}
You can have as much implementation as you want, but you need to have proper instance of PhotoImporter by Dependency Injection. Everything else will work smoothly.
This is how I could do this:
public class PhotoImporter
{
private PhotoLoader _photoLoader;
public PhotoImporter(PhotoLoader photoLoader)
{
_photoLoader = photoLoader;
}
public void ImportPhoto(PhotoBase photo)
{
var childType = photo.GetType();
dynamic childPhoto = Convert.ChangeType(photo, childType);
_photoLoader.Load(childPhoto);
}
}
You can simplify your ImportPhotoby using pattern matching:
public void ImportPhoto(photoBase photo)
{
switch(photo)
{
case FilePhoto filePhoto:
loader.Load(filePhoto);
break;
case ExternalPhoto externalPhoto:
loader.Load(externalPhoto);
break;
}
}
But this is only syntactic sugar and doesn't solve your real problem. What might help is a abstract Load method in your base class:
public abstract class PhotoBase
{
public string Path { get; set; }
public abstract void Load();
}
You have to implement this method in your child classes. If you call the method, the correct implementation will be chosen.
Online demo: https://dotnetfiddle.net/LfkxBQ

Overloading abstract generic methods in C#

I'm trying to implement a generic abstract method with a type constraint, then Implement it multiple times using different specified types.
public abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
public class DashAbility : Ability
{
public override void BindToStation<NavStation>(NavStation station){ }
public override void BindToStation<CannonStation>(CannonStation station){ }
}
But I get an error which says the method has already been defined with the same paramater types.
I'm guessing that the compiler treats any generic paramater as the same in terms of the method signature, so these two methods look the same to it.
Still though, I'm wondering if theres a way to have generic method overloading using specific types.. ?
You can't do exactly what you want, but you can try an approach like this:
interface IBindableTo<T> where T : Station
{
void BindToStation(T station);
}
abstract class Ability
{
public abstract void BindToStation<T>(T station) where T : Station;
}
class DashAbility : Ability, IBindableTo<NavStation>, IBindableTo<CannonStation>
{
public override void BindToStation<T>(T station)
{
if (this is IBindableTo<T> binnder)
{
binnder.BindToStation(station);
return;
}
throw new NotSupportedException();
}
void IBindableTo<NavStation>.BindToStation(NavStation station)
{
...
}
void IBindableTo<CannonStation>.BindToStation(CannonStation station)
{
...
}
}
Hope this helps.
C# doesn't support specialization in that way, and neither does C++ easily when you want to specialize on runtime type.
But you can use polymorphism, so you can use double-dispatch:
public abstract class Station {
internal abstract void DashBindToStation();
}
public class NavStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public class CannonStation : Station {
internal override void DashBindToStation() {
throw new NotImplementedException();
}
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public override void BindToStation(Station station) {
station.DashBindToStation();
}
}
Another possibility with C# is to use runtime dispatching using dynamic:
public abstract class Station {
}
public class NavStation : Station {
}
public class CannonStation : Station {
}
public abstract class Ability {
public abstract void BindToStation(Station station);
}
public class DashAbility : Ability {
public void BindToStation(NavStation station) {
}
public void BindToStation(CannonStation station) {
}
public override void BindToStation(Station station) {
BindToStation((dynamic)station);
}
}

"Base class params are not always used" code smell

Suppose you had such code:
public Base
{
abstract void Register();
}
public Registrator1: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
public Registrator2: Base
{
override void Register()
{
//uses the current state of the object to populate the UI captions
}
}
But When you receive a new business rule asking you to write Registrator3 which actually registers based on some parameter and you change your code base to the next:
public Base
{
abstract void Register(externalParam);
}
public Registrator1: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate theUI
}
}
public Registrator2: Base
{
override void Register(externalParam)
{
//uses the current state of the object to populate the UI
}
}
public Registrator3: Base
{
override void Register(externalParam)
{
//uses a DDD - service passed in the params to populate the UI
}
}
But Registrator1 and Registrator2 do not need that param and the code becomes smelly. What are the ways to re-write this code?
You could use an object as a parameter here; which is commonly used in scenarios where the number of parameters can vary depending on the call being used.
struct RegistrationInfo
{
public static readonly RegistrationInfo Empty = new RegistrationInfo();
public string Username;
public string CustomerName;
public string Validity;
}
abstract class Base
{
public abstract void Register(RegistrationInfo info);
// If you want to retain the paramaterless call:
public void Register()
{
Register(RegistrationInfo.Empty);
}
}
class Registrar1 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.Username == null) throw new ArgumentNullException("info.Username");
}
}
class Registrar2 : Base
{
public override void Register(RegistrationInfo info)
{
if (info.CustomerName == null) throw new ArgumentNullException("info.CustomerName");
}
}
This has the advantage that you don't need to change method parameters (which is breaking interface) each time a parameter is added. The usage also becomes somewhat self-documenting:
var r = new Registrar1();
r.Register(new RegistrationInfo(){ Username = "JimJoe" });
r.Register(RegistrationInfo.Empty);
It's like air freshener for this type of code smell, while it's still smelly; you can make it smell nicer.
Finally you can make the call-site cleaner by making it a params argument (this has a small amount of overhead); in all honesty though it is more smelly because it's a language hack. Finally you could improve it with generics:
class RegistrationInfo
{
}
class RegistrationInfo1 : RegistrationInfo
{
public string Arg;
}
class RegistrationInfo2 : RegistrationInfo
{
public int Arg;
}
interface IBase<in TRegistration>
where TRegistration : RegistrationInfo
{
void Register(TRegistration registration);
}
class Base : IBase<RegistrationInfo>
{
public void Register(RegistrationInfo registration)
{
}
}
class Registrar1 : IBase<RegistrationInfo1>
{
public void Register(RegistrationInfo1 arg)
{
}
}
class Registrar2 : IBase<RegistrationInfo2>
{
public void Register(RegistrationInfo2 arg)
{
}
}
Is it not possible to contain the logic for externalParam in Registrator3?
In other words, Registrator3 uses the param, then calls the unmodified parameterless base?
A lot really depends on where the logic belongs. If it is something intrinsic to the base, then put it in the base, and either overload the Register() function or supply a default value for the param so that sub classes don't need to provide it.
Assuming you want to reuse the registration logic from the base class, you could update the code as follows:
public class Base
{
public virtual void Register(object externalParam)
{
// base registration logic goes here
}
}
public class Registrator1: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator2: Base
{
public override void Register(object externalParam)
{
base.Register(null);
// custom registration logic goes here
}
}
public class Registrator3: Base
{
public override void Register(object externalParam)
{
base.Register(externalParam);
// custom registration logic goes here
}
}
HTH,
Cosmin
EDIT: Updated code to compile.

Cannot add object to list

I'm trying out an example of using Domain Events to notify of when something has happened in a system (borrowed from here and here).
I'm really close to getting the code working how I want, however, I've hit a bit of a brick wall. Here is my DomainEvents class:
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);
}
}
}
The above won't compile because Actions.Add cannot accept callback since it's a IEventHandler<T> type rather then a IEventHandler<IDomainEvent> type. Here's some more code to clarify.
This is called from my console application:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler implements IEventHandler<CustomerHasUnpaidDuesEvent>, where CustomerHasUnpaidDuesEvent implements 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; }
}
This is what I don't get - if CustomerHasUnpaidDuesEvent implements IDomainEvent, then why is the call to Actions.Add failing? How can I resolve this?
EDIT:
To make things clearer, here is entire code for my test app:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "test#dfsdf.com";
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));
}
}
Cheers.
Jas.
There is no need for your Register method to be generic:
public static void Register(IEventHandler<IDomainEvent> callback)
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
Edit:
The problem is that in order to have IEventHandler<CustomerHasUnpaidDuesEvent> to be in the list of IEventHandler<IDomainEvent>s, we need T to be a covariant template parameter in IEventHandler<T> (which is declared as IEventHandler<out T>). However in order to allow the function Handle(T arg), we need T to be contravariant. So strictly this way won't work. Imagine: if we really could insert an IEventHandler<CustomerHasUnpaidDuesEvent> into a list of IEventHandler<IDomainEvent>s, than someone might try to call Handle with the argument of some type which derives from IDomainEvent but is not a CustomerHasUnpaidDuesEvent! This should be impossible to do.
The solution is that we don't need the exact type at Register, so we can keep a reference to a generic base interface. The implementation is here: http://ideone.com/9glmQ
Old answer is not valid, kept below for consistency.
Maybe you need to declare IEventHandler to accept T as a covariant type?
interface IEventHandler<in T> where T: IDomainEvent
{
void Handle();
// ...
}
Edit: surely CustomerHasUnpaidDuesEvent is an IDomainEvent, but you need IEventHandler<CustomerHasUnpaidDuesEvent> to be a IEventHandler<IDomainEvent>. This is exactly what covariance does. In order to allow that, your template parameter in IEventhandler must be declared covariant (<in T> instead of just <T>).

Categories

Resources