手动解析由属性约束绑定的依赖项
Manually resolving dependencies bound by attribute constraints
我有两个绑定:
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
最终会导致 WhosebugException
,因为当此设置为 false 时,该参数会在请求中持续存在。将它设置为 true
会导致它不传播 - 与我预期的相反。
另一种方法是用 NamedAttribute
替换 SharedCacheAttribute
。这是一个例子:
//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
将包含确定是检索 "default" 还是共享缓存的逻辑。它需要检查属性,然后解析并 return 相应的实例。因此 ICache
:
还需要两个命名绑定
Bind<ICache>().ToMethod(...).Named("default")
.BindingConfiguration.IsImplicit = true;
Bind<ICache>().ToMethod(...).Named("shared");
.BindingConfiguration.IsImplicit = true;
备注:.BindingConfiguration.IsImplicit = true;
是必需的,否则 ninject 认为 ICache
(没有名称)的请求由所有绑定实现 - 并抛出异常。请求只需要由提供者完成。
我有两个绑定:
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
最终会导致 WhosebugException
,因为当此设置为 false 时,该参数会在请求中持续存在。将它设置为 true
会导致它不传播 - 与我预期的相反。
另一种方法是用 NamedAttribute
替换 SharedCacheAttribute
。这是一个例子:
//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
将包含确定是检索 "default" 还是共享缓存的逻辑。它需要检查属性,然后解析并 return 相应的实例。因此 ICache
:
Bind<ICache>().ToMethod(...).Named("default")
.BindingConfiguration.IsImplicit = true;
Bind<ICache>().ToMethod(...).Named("shared");
.BindingConfiguration.IsImplicit = true;
备注:.BindingConfiguration.IsImplicit = true;
是必需的,否则 ninject 认为 ICache
(没有名称)的请求由所有绑定实现 - 并抛出异常。请求只需要由提供者完成。