Reputation: 49
I have a customerservice for 6 different shops with 3 different shopystem apis, so I have 3 libs in my Project
Like
Shopsytem 1 -> (Lib1)
Shop A
Shop B
Shop C
Shopsystem 2 -> (Lib2)
Shop D
Shop E
Shosystem 3 -> (Lib3)
Shop F
I have a "Contactcontroller" in Lib1, Lib2/Lib3 inherited from Lib1
Now I need to call a function like
contractService.getContracts();
With my Interface
public interface IContractService
{
List<ContractData> GetContracts()
}
In each Lib I have a class like
public Shopsystem1ContractService : IContractService {
List<ContractData> GetContracts(){...}
}
public Shopsystem2Contractservice : IContractService {
List<ContractData> GetContracts(){...}
}
public Shopsystem3ContractService : IContractService {
List<ContractData> GetContracts(){...}
}
But Now I need something like this:
public Shopsystem1ContractService : IContractService {
List<Shopsystem1ContractData> GetContracts(){...}
}
public Shopsystem2ContractService : IContractService {
List<Shopsystem2ContractData> GetContracts(){...}
}
public Shopsystem3contractservice : IContractservice {
List<Shopsystem3ContractData> GetContracts(){...}
}
Update:
Now I use a generic interface according to juharr and Julius:
interface IContractService<TContract> where TContract : ContractData
{
List<TContract> GetContracts();
}
public Shopsystem1ContractService : IContractService<Shopsystem1ContractData>
{
List<Shopsystem1ContractData> GetContracts(){...}
}
public Shopsystem2ContractService : IContractService<Shopsystem2ContractData>
{
List<Shopsystem2ContractData> GetContracts(){...}
}
public Shopsystem3contractservice : IContractservice<Shopsystem3ContractData>
{
List<Shopsystem3ContractData> GetContracts(){...}
}
IoCModule:
ioc.Register<IContractService<Shopsystem1ContractData>, Shopsystem1contractservice>();
ioc.Register<IContractService<Shopsystem2ContractData>, Shopsystem2contractservice>();
ioc.Register<IContractServic<Shopsystem3ContractData>, Shopsystem2contractservice>();
But how can I implement this in my ContractController?
private readonly IContractService<ContractData> contract;
public KontaktController(
IContractService<ContractData> contract,
{
this.contract = contract;
}
IContractService needs a type, how does it know Shopsystem{1-3}ContractData?
The easy way would be to create a Contractcontroller in Lib2 and Lib3, but I would be great if I could do that in my globallib (lib1). I have controllers in Lib 2 and Lib3, but only for explicit endpoints
Upvotes: 0
Views: 75
Reputation: 4339
This looks like a case for generics.
You should make the IContractservice
generic. Like this:
interface IContractservice<TContract> where TContract : ContractData
{
List<TContract> GetContracts();
}
The where
makes it so the generic type you pass in has to be derived from ContractData
.
You would then implement it like this:
class Shopsystem1contractservice : IContractservice<Shopsystem1contractData>
{
public List<Shopsystem1contractData> GetContracts()
{
}
}
Let's talk about your edit:
In the current situation, I'd say you can't do that. You are correct that there is no way of knowing which of the three should be injected. That's why you should do one of the following things:
IContractservice<Shopsystem1contractData>
inside your controller. IContract<ContractData>
instead of a more explicit one. Both of these probably break your system so why are you doing it like this? You will always need a way of choosing one of the three and you could (as mentioned in point 2) register the one to use if asked for the general one.
I think like this would make the most sense:
ioc.Register<IContract<ContractData>, Shopsystem2contractservice>();
The other three things you registered are redundant since you currently only seem to have one implementation of IContract<Shopsystem1ContractData>
, etc. You do however have multiple implementations of IContract<ContractData>
so that's what you should register.
You should also be able to register ContractData
so everytime you ask for ContractData
it'll take the one you defined (eg. Shopsystem1contractData
).
There is a flaw in your design so it's very hard to determine which would be the correct solution for your case.
Upvotes: 1
Reputation: 32296
You can make the interface generic so you can specify the desired type in the implementations like this.
public interface IContractService<TData> where TData : ContractData
{
List<TData> GetContracts();
}
public Shopsystem1ContractService : IContractService<Shopsystem1ContractData>
{
List<Shopsystem1ContractData> GetContracts(){...}
}
public Shopsystem2ContractService : IContractService<Shopsystem2ContractData>
{
List<Shopsystem2ContractData> GetContracts(){...}
}
public Shopsystem3contractservice : IContractservice<Shopsystem3ContractData>
{
List<Shopsystem3ContractData> GetContracts(){...}
}
Upvotes: 1