Reputation: 34109
My application deals with multiple clients and each client has different settings.
So I have decided to use IOC container to register each client specific settings using a key
. Then i am locating ClientSettings based on akey
. key
value will be available during runtime.
C# Library MyCompany.BO
public class ClientSettings : IClientSettings
{
public string ClientApiKey { get; private set}
public string ClientId { get; private set}
public static IClientSettings Load(string clientname)
{
// Load the client specific information from JSON file using clientname
var cs = new ClientSettings();
cs.ClientApiKey = "Some client specific key";
cs.ClientId = "Some client specific key";
return cs;
}
}
Consumed in MyCompany.BO namespace
public class RuleEngine : IRuleEngine
{
IFactory _factory;
RuleEngine(IFactory factory)
{
factory = _factory;
}
public void Run(string request)
{
var clientname = ParseStringToGetClientName(request)
var clientSettings = ServiceLocator.Current.GetInstance<IClientSettings>(clientname);
var service = _factory.GetService(clientname);
service.DoWork(clientSettings);
}
}
Main Application registering the client settings
var container = new UnityContainer();
var clientASettings = ClientSettings.Load("ClientA");
var clientBASettings = ClientSettings.Load("ClientB");
var clientCSettings = ClientSettings.Load("ClientC");
// register singleton instance
container.RegisterInstance("ClientA", clientASettings);
container.RegisterInstance("ClientB", clientBSettings);
container.RegisterInstance("ClientC", clientCSettings);
Question
The RuleEngine class is using Microsoft.Practices.ServiceLocation.ServiceLocator
to locate ClientSettings
based on the key
. That means C# library where rule engine is implemented needs to use the same IOC that application is using. (Which is Unity in this case)
How do I make library unaware of IOC container?
How do I inject clientsettings here without using ServiceLocator when the key
value known during runtime?
Is the factory pattern the only way to achieve this? (For example the way I am locating service _factory.GetService(clientname)
)
Upvotes: 0
Views: 904
Reputation: 233150
These three lines:
var clientname = ParseStringToGetClientName(request);
var clientSettings = ServiceLocator.Current.GetInstance<IClientSettings>(clientname);
var service = _factory.GetService(clientname);
look like pure plumbing with little or no branching. Move that part to your Composition Root. Since you've put this in your Composition Root, there's no reason to attempt to abstract away any DI Container you may use. Instead, you can simply compose the desired services using the API of the DI Container, and the reusable class library will not need to know how that happened.
Upvotes: 4