I am in this situation where my service interface is being implemented by two service classes.
For example,
IFooService
is implemented by FooService
and FooWithExtraInfoService
Here is the interface:
public interface IFooService
{
Foo GetEntity(string fieldName, stringFieldValue);
}
Here is FooService
:
public class FooService: BarService, IFooService
{
public FooService(ILogService logservice): base(logservice)
{
}
public Foo GetEntity(string fieldName, string fieldValue)
{
//here goes the logic
}
}
Here is FooWithExtraInfoService
:
public class FooWithExtraInfoService: BarService, IFooService
{
public FooWithExtraInfoService(ILogService logservice): base(logservice)
{
}
public Foo GetEntity(string fieldName, string fieldValue)
{
//one possible option could be
var foo = new FooService(logservice).GetEntity(fieldName, fieldValue)
//do additional stuff
foo.SomeField = "abc";
}
}
As you can see one option could be creating new object of FooService and then telling unity to register type where IFooService
is implemented by FooWithExtraInfoService
.
Something like:
container.RegisterType<IFooService, FooWithExtraInfoService>();
But is there some other way where I don't have to create new object of FooService
?
//one possible option could be
var fooService = new FooService(logservice).GetEntity(fieldName, fieldValue)
//do additional stuff
And let Unity handle it somehow?
Or should I create different interface for FooWithExtraInfoService
?
I don't know what is the best way to approach this problem at this point.
Any suggestions would be helpful.
Given both inherit from
BarService
, create an intermediate typeFooServiceBase
that implements the interface:And let
FooWithExtraInfoService
andFooService
inherit from that.This seems like a good candidate for the decorator pattern.
The decorator pattern wraps the existing service, adding additional functionality to it without having to make changes to it. This allows you to cleanly separate responsibilities of what
FooService
does fromFooWithExtraInfoService
and still allow the DI container to provide the "inner" instance.Then you just need to wire it up with your DI container like:
In Unity, this registration could be done like:
Unlike using inheritance, the decorator is loosely coupled from
FooService
. TheILogService
does not need to be passed into the decorator only so it can be forwarded into the superclass constructor. Additionally, you can easily add another decorator class betweenFooWithExtraInfoService
andFooService
simply by changing the DI configuration.I believe in your case you should use
Composition
... mean have a property of typeFooService
rather like below since you just want to use theGetEntity()
method and have no intention of extending itThis seems like the
FooWithExtraInfoService
is meant to beFooService
, but with extra info, right?So then, actually make it a
FooService
class with extra info. Give theGetEntity
function inFooService
thevirtual
keyword, and it can be overridden in child classes. This then allows you to have a new override inFooWithExtraInfoService
which can simply call its parent implementation.The adapted
FooService
class:The implementation:
When you can't always rely on the interface alone to define the behavior your service-consumers require, one alternative is to register one or both of your concrete implementations for DI.
Then any class that can safely depend on the simpler
IFooService
can declare a dependency on that, and those which you know will need the additional capabilites fromFooWithExtraInfoService
can depend upon that instead. AndFooWithExtraInfoService
can even declare a dependency onIFooService
to inject the simpler implementation.Basically, interface services are useful, but don't get too hung up on trying to use them in every case.