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,如 Func
、Lazy
和集合.
顺便说一句,如果您不喜欢 KeyValuePair
,您可以使用 Tuple
。
在我的实现中,我需要根据 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,如 Func
、Lazy
和集合.
顺便说一句,如果您不喜欢 KeyValuePair
,您可以使用 Tuple
。