Reputation: 29427
I have a generic interface IService
which is concretely implemented by three or four implementations.
public interface IService {
void HandleRequest( RequestData data );
}
public class AService : IService {
public void HandleRequest( RequestData data ) {
}
}
public class BService : IService {
public void HandleRequest( RequestData data ) {
}
}
The rules to choose a concrete implementation versus a different one are actually implemented into a method which analyze the input object (RequestData
) and based on some data coming from the database choose the correct concrete class.
I need now to do constructor injection in a controller class and would like to configure Ninject to handle the instance creation of those objects like in the following sample
public class MyController : ApiController
{
private readonly IService _service;
public MyController( IService service ) {
_service = service;
}
}
Is there any way to write such an extension to support Ninject in the decision process? I am thinking to something like this
Bind<IService>().To<AService>().IfConditionIsTrue( new CustomProvider() );
Bind<IService>().To<BService>().IfConditionIsTrue( new CustomProvider() );
public class CustomProvider {
public bool ApplyCustomLogic() {
RequestData rd = GetParameter();
[...]
//custom logic implementation here..
}
}
Also, how I can create an instance on the fly by leveraging ninject functionalities? For example, inside a method at a certain time, I need an instance of IService
. How can I ask ninject to supply a concrete instance on the fly? I have only worked with constructor injection until now.
Upvotes: 1
Views: 54
Reputation: 172835
I don't think you should 'pollute' your DI configuration with this. Instead solve this by using a proxy class that can dispatch the RequestData
messages to the correct handler implementation:
public sealed class ServiceDispatcher : IService
{
private readonly Kernel kernel;
public ServiceDispatcher(Kernel kernel) {
this.kernel = kernel;
}
public void HandleRequest(RequestData data) {
Type implementationType;
// custom logic to determine correct IService based on data here..
// and resolve that implementation from the kernel.
IService realService = (IService)this.kernel.Get(implementationType);
realService.HandleRequest(data);
}
}
Now you can bind your ServiceDispatcher
class to IService
and allow it to be injected into anyone who depends on IService
. The dispatcher will ensure that the request is dispatched to the correct implementation.
But you might want to consider using a generic abstraction such as IService<T>
. Take a look at this article for instance.
Upvotes: 2