C
C#14mo ago
Florian Voß

✅ Dependency Inversion Principle, Dependency Injection

I have a huge brain fart, hopefully someone can clear it out. Imagine the following Scenario: You've created a Service that you wanna inject into the classes that depend on it. To respect Dependency Inversion principle we wanna achieve lose coupling, so we wanna create an abstraction for our Services. But the issue is there are no members that all my Services have in common, hence we can't really abstract any functionality into a seperated interface. But we need an interface to achieve louse coupling, also for later unit tests when our Service needs to get mocked. A common solution to this according to my research is to create a Marker interface. That means we create an empty interface that doesn't contain any members, it's only purpose is to represent an abstraction so that we can achieve lose coupling. Now here is the issue:
public class DependantClass{
private IService _service;
public DependantClass(IService service){
_service = service;
}
}
public class DependantClass{
private IService _service;
public DependantClass(IService service){
_service = service;
}
}
Now the issue is that this service object is pretty much useless as it's type reference doesn't expose any members. So in order to call the members of our Service, we would have to cast to a more concrete type here which negates the whole point of Dependency Inversion. So what to do now? Take Concrete type reference here and give up on dependency inversion principle? Doesn't seem right to me. But casting our MarkerInterface to more concrete typereference seems even worse. So what do I do now?
4 Replies
Pobiega
Pobiega14mo ago
you wouldnt use a broad IService, you'd use a ISpecificService
chef drone builder
Dont create one interface for all your services. Create one interface per service.
Nergy101
Nergy10114mo ago
I think the marker interface is confusing you. Normally your interfaces would be pretty specific to the functionality you want to achieve E.g ICow - walk() - stop() - Moo() ICat - walk(int speed) <- different! - stop() - Meow() <- different If I wanted to program a cat I'd use the ICat and if I wanted to program a cow I'd use ICow. Now what if I want to list all animals I have interfaces for? That's what you use a "marker" interface for. I'd add
:IAnimal
:IAnimal
to ICat and the ICow interfaces. Now I could list out all animals and maybe add more generic functionality like "MakeASound" or the "stop" method since both ICat and ICow have the same Stop method signature Does this help?
Florian Voß
Florian Voß14mo ago
not at all, knew everything you've told me here actually but I appreciate trying to help me out! @kocha @Pobiega I will do exactly that, tyvm!
Want results from more Discord servers?
Add your server
More Posts