DryIoc - 注入带有附加参数的 Func 作为工厂方法

DryIoc - inject a Func with additional parameters as a Factory-method

在我的实现中,我需要根据 servicekey 动态解析服务。因此,我想传递一个 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));

但在documentation中,DryIoc 推荐在Delegates 之上使用工厂方法。 我玩过很多 Made.Of-notations(我发现记录很少),但还没有找到一个有效的。

这可以用(静态)工厂方法实现吗?

如果您需要动态 select 基于密钥的服务但不依赖服务定位器反模式(不将 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 容器能够组成 wrappers,如 FuncLazy 和集合.

顺便说一句,如果您不喜欢 KeyValuePair,您可以使用 Tuple