我有一个服务界面
interface IService { }
和许多实现
class ServiceA : IService { }
class ServiceB : IService { }
class ServiceDefault : IService { }
我的课程耗费IService
,比如
class ServiceUse
{
public ServiceUse(IService svc) { }
}
应根据上下文状态将其中一个IService
实现注入到使用类中。
为实现这一目标,我有ServiceProvider
类
static class ServiceNames
{
public const string ServiceA = "ServiceA";
public const string ServiceB = "ServiceB";
public const string ServiceDefault = "ServiceDefault";
}
class ServiceProvider : Provider<IService>
{
protected override IService CreateInstance(IContext context)
{
ServiceKindEnum kind = GetServiceKind(HttpContext.Current);
string bindingName = $"Service{kind}";
if (context.Kernel.CanResolve<IService>(bindingName))
return context.Kernel.Get<IService>(bindingName);
return context.Kernel.Get<IService>(ServiceNames.ServiceDefault);
}
...
}
绑定是
Bind<IService>().To<ServiceA>()
.Named(ServiceNames.ServiceA);
Bind<IService>().To<ServiceB>()
.Named(ServiceNames.ServiceB);
Bind<IService>().To<ServiceDefault>()
.Named(ServiceNames.ServiceDefault);
Bind<IService>().ToProvider<ServiceProvider>()
.WhenInjectedInto(typeof(ServiceUse));
每当出现消耗IService
的其他类时,例如
class AnotherServiceUse
{
public AnotherServiceUse(IService svc) { }
}
我必须添加其类型作为指向WhenInjectedInto
的绑定的ServiceProvider
条件的参数
Bind<IService>().ToProvider<ServiceProvider>()
.WhenInjectedInto(typeof(ServiceUse), typeof(AnotherServiceUse));
因此,WhenInjectedInto
的参数列表在开发过程中可能会非常不稳定,有时这不方便。
我正在寻找一种不太关注WhenInjectedInto
参数列表的方法。我觉得我需要WhenInjectedIntoAny
(或简称WhenInjected
)
Bind<IService>().ToProvider<ServiceProvider>()
.WhenInjected(); //target is not matter
有哪些选择?
答案 0 :(得分:1)
正如您当前问题中的代码现在所示,您有两个用于解析IService
的用例:
WhenInjectedInto
约束。如果您的示例实际上是完整的,那么整个WhenInjectedInto
可以通过一个条件大大简化,该条件表明不应该对请求有约束。因此,您的绑定应如下所示:
Bind<IService>().To<ServiceA>()
.Named(ServiceNames.ServiceA);
Bind<IService>().To<ServiceB>()
.Named(ServiceNames.ServiceB);
Bind<IService>().To<ServiceDefault>()
.Named(ServiceNames.ServiceDefault);
Bind<IService>().ToProvider<ServiceProvider>()
.When(request => request.Constraint == null);
在您的具体示例中,您还可以通过执行以下操作为ToProvider<ServiceProvider>()
绑定提供“首选项”:
Bind<IService>().ToProvider<ServiceProvider>()
.When(request => true);
这将使Ninject选择此实现,如果有多个可供选择。提示:如果您有其他条件(When...
)评估为true,那么这将不起作用。要将其移动到扩展方法中,请添加如下代码:
public static class NinjectExtensions
{
public static IBindingInNamedWithOrOnSyntax<T> MakePreferredBinding<T>(
this IBindingWhenSyntax<T> syntax)
{
return syntax.When(req => true);
}
}
如果这对您的方案不起作用,因为请求具有其他约束而不仅仅是名称,那么您可以使用基于参数的解决方案。对于感兴趣的读者,简而言之就是这样:
IParameter
实现。When(...)
创建用于绑定的自定义扩展方法。这应检查自定义参数是否在上下文中以及字符串是否匹配。将此应用于所有“命名”服务绑定,而不是Named(...)
。.Named(...)
进行选择。