Dependency injection. How to resolve dependency based on value and not type?
I have one interface and two classes (implemented from this interface) in my application as shown below:
public interface ISMSServiceProvider
{
NotificationSentResponse Send(SMSMessage sms);
}
public class NexmoProvider: ISMSServiceProvider
{
NotificationSentResponse Send(SMSMessage sms);
}
public class TwilioProvider: ISMSServiceProvider
{
NotificationSentResponse Send(SMSMessage sms);
}
In some places in my application I need to use NexmoProvider and in some places TwilioProvider. This was assumed based on the value of the following enumeration variable:
public enum NotificationProvider
{
Twilio = 1,
Nexmo = 2
}
I am using a service stack in my application and having the following code to resolve the dependency:
container.RegisterAutoWiredAs<TwilioProvider, ISMSServiceProvider>();
But as you can see, there is nothing in the ISMSServiceProvider that would allow me to register two different types at the same time.
Can anyone think of what changes I might need to the structure below to allow me to use any of the Nexmo or Twilio provider classes at runtime?
source to share
You can only have a single registration per interface or type so that this registration:
container.RegisterAutoWiredAs<TwilioProvider, ISMSServiceProvider>();
An instance will return TwilioProvider
when resolved from the interface, for example:
var smsProvider = container.Resolve<ISMSServiceProvider>();
If you want to be able to register both types, you can register on a specific type, for example:
container.RegisterAutoWired<TwilioProvider>();
container.RegisterAutoWired<NexmoProvider>();
Allowed:
var twilio = container.Resolve<TwilioProvider>();
var nexmo = container.Resolve<NexmoProvider>();
If you want to allow the use of Enum you can register a factory like:
public class SmsFactory
{
public ISMSServiceProvider Resolve(NotificationProvider provider) =>
provider == NotificationProvider.Twilio
? HostConfig.Resolve<TwilioProvider>()
: HostConfig.Resolve<NexmoProvider>();
}
container.Register(c => new SmsFactory());
What can you enter into your Service with:
public SmsFactory SmsFactory { get; set; }
Then use as usual, ie:
var smsProvider = SmsFactory.Resolve(NotificationProvider.Twilio);
source to share