2016-08-19 13 views
0

Мое приложение имеет дело с несколькими клиентами, и каждый клиент имеет разные настройки. Итак, я решил использовать контейнер IOC для регистрации каждого конкретного клиента с помощью key. Затем я устанавливаю ClientSettings на основе key. Значение key будет доступно во время выполнения.Как написать библиотеку классов C# IOC и ServiceLocator?

C# библиотека 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; 
    } 
} 

Потребляемый в MyCompany.BO имен

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); 
    } 
} 

Основные приложения регистрирующие параметры клиента

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); 

Вопрос
RuleEngine класс использует Microsoft.Practices.ServiceLocation.ServiceLocator, чтобы найти ClientSettings на основе key. Это означает, что библиотека C#, где реализован механизм правил, должна использовать тот же IOC, что и приложение. (Что в этом случае является Unity)
Как мне сделать библиотеку не осведомленной о контейнере IOC?
Как мне проинсталлировать настройки клиентов здесь, не используя ServiceLocator, когда значение key известно во время выполнения? Является ли заводская модель единственным способом достижения этого? (Например, так, как я местонахождение службы _factory.GetService(clientname))

+2

Взгляните на концепцию [Корень композиции] (http://blog.ploeh.dk/2011/07/28/CompositionRoot/), и в случае, если вы пишете библиотеку многократного использования, прочитайте [эту статью] (http://blog.ploeh.dk/2014/05/19/di-friendly-library/). – Steven

+0

@Steven Спасибо. Я посмотрел на Корзину композиции, короче говоря, ее местоположение в вашем приложении, где вы регистрируете типы с контейнером. Это единственное место, где мы должны использовать контейнер. и это именно то, что я делаю. Мое приложение - это приложение MVC, поэтому все типы будут регистрироваться в global.ascx с контейнером, как было предложено. Однако это не проблема, которую я опубликовал ... (Я также прошел через другую ссылку) – LP13

+0

Чтобы ответить на часть вашего вопроса: нет, фабрики - это не единственный способ и лучший способ достичь этого. Смотрите это: https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=100 – Steven

ответ

4

Эти три линии:

var clientname = ParseStringToGetClientName(request);  
var clientSettings = ServiceLocator.Current.GetInstance<IClientSettings>(clientname);   
var service = _factory.GetService(clientname); 

выглядеть чистой водопроводным практически без ветвления. Переместите эту часть на ваш Composition Root. Так как у вас есть put this in your Composition Root, вы можете использовать no reason to attempt to abstract away any DI Container. Вместо этого вы можете просто составить нужные службы, используя API контейнера DI, а библиотека классов многократного использования не обязательно будет знать, как это произошло.

+0

Услуги также разрешаются на основе значения времени выполнения. Если я решил зарегистрировать службы с контейнером DI в корне композиции, как вы предлагаете, как бы вы получили экземпляр службы без использования заводского или сервисного локатора? (это та же проблема с настройками клиента). Единственная разница между службами и настройками клиентов: для каждого запроса я хочу новый экземпляр службы, в то время как Clientsettings может быть одноточечным. – LP13

+0

также, какой бы подход я ни использовал (заводские или другие сложные варианты), ему нужно вернуть экземпляр singleton, который регистрируется в контейнере в корне композиции. – LP13

+2

[контейнер DI, инкапсулированный внутри корня композиции, не является локатором службы) (http: // blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/). Это означает, что ваша фабричная реализация может вызвать контейнер, если он находится внутри * корня композиции. – Steven

 Смежные вопросы

  • Нет связанных вопросов^_^