2010-09-21 4 views
2

У меня есть интерфейс, например ISomeService. ISomeService предоставляет общую службу, но реализации могут отличаться. Таким образом, они будут иметь разные зависимости.Внедрение фабрики или поставщика общих услуг в Autofac

Рассмотрим:

interface ISomeService 
{ 
    void DoSomething(); 
} 

class SomeServiceA : ISomeService 
{ 
    public SomeServiceA(DependencyOne one, DependencyTwo two) 
    { 
    } 


    public void DoSomething() 
    { 
    } 
} 

class SomeServiceB : ISomeService 
{ 
    public SomeServiceB(DependencyThree three) 
    { 
    } 

    public void DoSomething() 
    { 
    } 
} 

Теперь, реальность такова, что я не могу просто добавить зависимость к ISomeService в мой контроллер и сделать с ней. Мне нужно будет выбрать реализацию IService на основе того, что мне говорит пользователь, и мне, возможно, придется создать несколько копий службы, которую они выбрали.

Возможно, я должен был бы класс, который позволяет мне разрешить экземпляр ISomeService мне нужно, по типу:

class SomeServiceProvider 
{ 
    public T Get<T>() 
     where T : ISomeService 
    { 
      // uh oh, this is starting to have a bad smell... do I call the container? that's no good 
    } 

} 

Так что я мог

class SomeController 
{ 
    SomeServiceProvider ServiceProvider { get; set; } 

    public SomeController(ServiceProvider provider) 
    { ServiceProvider = provider; } 

    public void SomeAction(string serviceName) 
    { 
      ISomeService someService; 
      if (serviceName.Equals('SomeServiceA')) someService = ServiceProvider.Get<SomeServiceA>(); 
      else someService = ServiceProvider.Get<SomeServiceB>(); 
      someService.DoSomething(); 
    } 

} 

кажется, что делегат завода Autofac в не будет уместным здесь, и я не уверен, что делать иначе (кроме использования локатора сервисов). Любые рекомендации?

ответ

2

Это то, что вам нужно? Service types, names and keys

Услуги могут быть дополнительно идентифицированы с использованием имени службы. Используя этот метод, метод регистрации Named() заменяет As().

builder.Register<OnlineState>().Named<IDeviceState>("online"); 

Чтобы получить именованный службу, используется метод ResolveNamed():

var r = container.ResolveNamed<IDeviceState>("online"); 
+0

Я думаю, раздел ** Разрешение указателей ** в вашей ссылке будет делать что я хочу, хотя немного неудобно, что я должен написать компонент, который требует ссылки на Autofac. Но, полагаю, я могу справиться с этим. Благодаря! – HackedByChinese

+1

Я предлагаю создать SomethingFactory, который использует IIndex и реализует ISomethingFactory, который вы можете использовать в своих контроллерах - лучше всего в обоих мирах! :) Такие типы, как IIndex, лучше всего хранить в инфраструктурной части вашего приложения, где он взаимодействует с контейнером IoC, а не с обычными компонентами приложения. Удачи вам! Ник –

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