我有两个绑定:
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateCache(
ctx.Kernel.Get<IXXX>(),
ctx.Kernel.Get<IYYY>()))
.WhenTargetHas<SharedCacheAttribute>()
.InSingletonScope()
.Named(BindingNames.SHARED_CACHE);
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateTwoTierCache(
ctx.Kernel.Get<ICache>(BindingNames.SHARED_CACHE),
ctx.Kernel.Get<IZZZ>()))
.InSingletonScope();
本质上我的想法是我有一个共享缓存(在第一个绑定中定义),但大多数时候我希望类使用一个双层缓存,它是相同的接口(ICache
)。因此,我限制使用属性约束来使用共享缓存(需要直接访问共享缓存的类只能使用[SharedCache]
)。
现在,问题在于第二个绑定,特别是这一行:
ctx.Kernel.Get<ICache>(BindingNames.SHARED_CACHE),
抛出一个异常,没有匹配的绑定可用,大概是因为第一个绑定的属性约束。
如何将第一个绑定的解析结果注入第二个绑定的工厂方法?
解决方法:
目前我在第一个绑定上使用Parameter
和更复杂的When()
约束。我的绑定现在看起来像这样:
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateCache(
ctx.Kernel.Get<IXXX>(),
ctx.Kernel.Get<IYYY>()))
.When(o => (o.Target != null &&
o.Target.GetCustomAttributes(typeof (SharedCacheAttribute), false).Any()) ||
o.Parameters.Any(p => p.Name == ParameterNames.GET_SHARED_CACHE))
.InSingletonScope();
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateTwoTierCache(
ctx.Kernel.Get<ICache>(new Parameter(ParameterNames.GET_SHARED_CACHE, true, true)),
ctx.Kernel.Get<IZZZ>()))
.InSingletonScope();
它按预期工作,但语法很复杂。另外,我原本希望Parameter
构造函数的'shouldInherit'参数必须设置为false
,以防止GET_SHARED_CACHE参数传递给子请求。实际上,将此设置为false
最终会导致StackOverflowException
,因为当此参数设置为false时,参数会在请求之间保持不变。将其设置为true
会导致它不会传播 - 与我预期的相反。
答案 0 :(得分:2)
另一种方法是将SharedCacheAttribute
替换为NamedAttribute
。这是一个例子:
//bindings
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateCache(
ctx.Kernel.Get<IXXX>(),
ctx.Kernel.Get<IYYY>()))
.InSingletonScope()
.Named(BindingNames.SHARED_CACHE);
Bind<ICache>().ToMethod(ctx => FactoryMethods.CreateTwoTierCache(
ctx.Kernel.Get<ICache>(BindingNames.SHARED_CACHE),
ctx.Kernel.Get<IZZZ>()))
.InSingletonScope();
// cache users
public class UsesSharedCache
{
public UsesSharedCache([Named(BindingNames.SHARED_CACHE)] ICache sharedCache)
{
}
}
public class UsesDefaultCache
{
public UsesDefaultCache(ICache defaultCache)
{
}
}
另一种选择是IProvider
。绑定看起来像这样:
Bind<ICache>().ToProvider<CacheProvider>();
CacheProvider
将包含确定是否检索“默认”或共享缓存的逻辑。它需要检查属性,然后解析并返回相应的实例。因此,ICache
需要另外两个命名绑定:
Bind<ICache>().ToMethod(...).Named("default")
.BindingConfiguration.IsImplicit = true;
Bind<ICache>().ToMethod(...).Named("shared");
.BindingConfiguration.IsImplicit = true;
备注:.BindingConfiguration.IsImplicit = true;
是必要的,因为否则ninject会考虑所有绑定都满足ICache
(没有名称)的请求 - 并抛出异常。该请求只需由提供商填写。