假设我有以下接口:
public interface ISomething { };
public interface IResolver
{
string ResolveBy(ISomething something);
}
现在我有两种解析器类型;一个提供最佳解决方案,但有机会失败的解决方案,一个解决方案,总能返回一个解决方案,这应该作为后备策略:
public class UnsafeResolver : IResolver
{
Random random = new Random();
public string ResolveBy(ISomething something)
{
if (random.NextDouble() > 0.5)
{
return "best solution ever!";
}
else
{
throw new InvalidOperationException("something went wrong...");
}
}
}
public class SafeResolver : IResolver
{
public string ResolveBy(ISomething something)
{
return "fallback solution";
}
}
现在我想在受保护的合成装饰器中合并两个解析器:
public class SafeguardedResolver : IResolver
{
private readonly IResolver unsafeResolver;
private readonly IResolver safeResolver;
// This is the problem with Ninject: Two parameters with same interface...
public SafeguardedResolver(IResolver unsafeResolver, IResolver safeResolver)
{
// guards omitted!
this.unsafeResolver = unsafeResolver;
this.safeResolver = safeResolver;
}
public string ResolveBy(ISomething something)
{
try
{
return unsafeResolver.ResolveBy(something);
}
catch (InvalidOperationException)
{
return safeResolver.ResolveBy(something);
}
}
}
所以我的问题是:如何使用Named Binding策略实现与Ninject 的绑定 ?我不想在我的域类中对容器有任何依赖,所以建议的解决方案对我不起作用
当然没有将ctor更改为IEnumerable<IResolver>
- 我想要两个单独的明确命名的参数!
为什么不能通过参数名称定义绑定?例如:
Bind<IResolver>().To<SafeguardedResolver>();
Bind<IResolver>().To<UnsafeResolver>()
.WhenInjectedInto<SafeguardedResolver>()
.AsParameter("unsafeResolver");
Bind<IResolver>().To<SafeResolver>()
.WhenInjectedInto<SafeguardedResolver>()
.AsParameter("safeResolver");
是否可以通过反射获取参数的名称?
我希望有人可以给我一个答案,如何解决这个问题(也许是通过使用另一个DI框架?)或者为什么这是不可能的。
答案 0 :(得分:1)
我不想在我的域类
中对容器有任何依赖
您可以使用命名绑定而无需引用类库中的容器,以下是您可以执行此操作的方法:
StandardKernel kernel = new StandardKernel();
kernel
.Bind<IResolver>()
.To<SafeguardedResolver>()
.WithConstructorArgument("unsafeResolver", c => c.Kernel.Get<IResolver>("unsafe"))
.WithConstructorArgument("safeResolver", c => c.Kernel.Get<IResolver>("safe"));
kernel
.Bind<IResolver>()
.To<UnsafeResolver>()
.Named("unsafe")
.BindingConfiguration.IsImplicit = true;
kernel
.Bind<IResolver>()
.To<SafeResolver>()
.Named("safe")
.BindingConfiguration.IsImplicit = true;
以下是使用Pure DI执行相同操作的方法:
var result = new SafeguardedResolver(new UnsafeResolver(), new SafeResolver());
在这种情况下,纯粹DI的简单性是IMO it is better than using a container的原因之一。