DryIoc - внедрить Func с дополнительными параметрами как Factory-метод - PullRequest
0 голосов
/ 04 октября 2019

В моей реализации мне нужно динамически разрешить сервис, основываясь на сервисном ключе. Поэтому я хочу передать Func, но не могу заставить это работать. Любая помощь в этом приветствуется.

Давайте иметь следующую реализацию:

public interface IMyInterface { 
  void Foo();
}
public class ClassA : IMyInterface { 
  void Foo() => BarA();
}
public class ClassB : IMyInterface { 
  void Foo() => BarB();
}
public class ClassC : IOtherInterface { 
  private readonly Func<string, IMyInterface> getInstance_;
  void ClassC(Func<string, IMyInterface> getInstance)
  {
    getInstance_ = getInstance;
  }

  void SomeLogic() 
  {
    IMyInterface implementation = getInstance("keyA");
    implementation.Foo();
  }
}
public static void Main()
{
  var c = new Container();
  c.Register<IMyInterface, ClassA>(serviceKey:"keyA");
  c.Register<IMyInterface, ClassB>(serviceKey:"keyB");
  c.Register<IOtherInterface, ClassC>();

  c.Resolve<IOtherInterface>(); 
}

Последний вызов завершается неудачно, что я понимаю. Исключение:

DryIoc.ContainerException: 'Unable to resolve IMyInterface with passed arguments [_String0] IsWrappedInFunc, IsDirectlyWrappedInFunc
  in wrapper Func<String, IMyInterface> FactoryId=10 with passed arguments [_String0] IsResolutionCall
  from Container with Scope {no name}
 with Rules with {TrackingDisposableTransients} and without {ThrowOnRegisteringDisposableTransient}
  with normal and dynamic registrations:
  ("keyA", {FactoryID=32, ImplType=ClassA})  ("keyB", {FactoryID=33, ImplType=ClassB}) '

Я выяснил, как зарегистрировать это с делегатом:

c.RegisterDelegate<Func<string, IMyInterface>>(r => (key) => c.Resolve<IMyInterface>(key));

Но в документации 1017 * DryIoc рекомендует использовать заводскиеМетоды выше делегатов. Я много играл с Made.Of-нотациями (которые я нахожу плохо документированными), но не нашел рабочую.

Возможно ли это с помощью (статического) метода Фабрики?

1 Ответ

1 голос
/ 04 октября 2019

Если вам нужно динамически выбрать сервис на основе ключа, но не полагаясь на анти-шаблон Service Locator (без внедрения IResolver в ClassC) - вы можете внедрить все доступные фабрики сервисов, как описано здесь https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/RegisterResolve.md#keyed-registrations во втором примере:

public class ClassC : IOtherInterface { 
  private readonly Func<string, IMyInterface> _implementations;
  void ClassC(KeyValuePair<string, Func<IMyInterface>>[] implementations)
  {
    _implementations = implementations;
  }

  void SomeLogic() 
  {
    var implementationFactory = _implementations.First(x => x.Key == "keyA").Value;
    var implementation = implementationFactory();
    implementation.Foo();
  }
}

Кстати, тот же подход используется в Autofac и, возможно, другими контейнерами DI, способными составлять оболочки , такие как Func, Lazy и коллекции.

BTW2. Если вам не нравится KeyValuePair, вы можете использовать Tuple.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...