由于我的MVC 3应用程序具有更好的性能,我正在从Ninject迁移到Simple Injector。我可以很好地注册存储库和服务。但是有一个使用
在Ninject中注册的过滤器 kernel.BindFilter<UserActivityAttribute>(FilterScope.Controller, 0).WhenControllerHas<UserActivityFilter>();
不会转换为Simple Injector。基本上我们使用该过滤器来记录用户活动,并且UserActivityFilter被指定为需要记录的控制器的属性。
答案 0 :(得分:0)
Simple Injector中没有BindFilter
个等效项。由于我不熟悉Ninject功能,我不能告诉你如何模拟它(虽然它当然可能)。
您可以做的当然是使用过滤器属性标记您的控制器,但这可能是您首先想要阻止的(如果我理解Ninject的BindFilter
功能的作用)。
就个人而言,我喜欢使用装饰器来应用横切关注点(例如日志记录)。您可以在服务层边界应用装饰器(例如this article显示)或在控制器级应用装饰器。
在控制器周围应用装饰器需要更多的工作。您需要更改为此注册控制器的方式。这可能是您目前的注册:
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
为了能够应用装饰器,您必须按基本类型(在这种情况下为IController
)注册控制器。有多种方法可以做到这一点,但我喜欢这种方法:
// We get all controller types for the current assembly.
var controllerTypes = SimpleInjectorMvcExtensions
.GetControllerTypesToRegister(container,
Assembly.GetExecutingAssembly());
// Here we register a collection of controllers.
container.RegisterAll<IController>(controllerTypes);
// We register a custom IControllerActivator.
container.RegisterSingle<IControllerActivator>(() =>
new SimpleInjectorControllerActivator(
container.GetAllInstances<IController>(),
controllerTypes));
由于控制器是按IController
基类型注册的,我们现在可以在控制器周围应用装饰器:
container.RegisterDecorator(typeof(IController),
typeof(UserActivityControllerDecorator), c =>
c.ImplementationType.GetCustomAttribute<UserActivityFilter>()
.Any());
不是将控制器映射到它们的具体类型(使用Register<HomeController>()
或Ninject的Bind<HomeController>().ToSelf()
,而是将它们注册为集合。自定义IControllerActivator
现在可以从集合中获取特定项:
// using System.Linq;
internal sealed class SimpleInjectorControllerActivator
: IControllerActivator
{
private readonly IEnumerable<IController> controllers;
private readonly Dictionary<Type, int> mapping;
public SimpleInjectorControllerActivator(
IEnumerable<IController> controllers,
Type[] controllerTypes)
{
this.controllers = controllers;
// Here we make a mapping from the controller type to
// the index in the controllers collection.
this.mapping = controllerTypes
.Select((type, index) => new { type, index })
.ToDictionary(i => i.type, i => i.index);
}
public IController Create(RequestContext requestContext,
Type controllerType)
{
int index = this.mapping[controllerType];
return controllers.ElementAt(index);
}
}
Create
方法使用Enumerable.ElementAt
方法
通过索引从集合中获取特定(装饰)控制器。 Simple Injector返回的集合实现IList<T>
,这允许ElementAt
使用IList<T>
索引器,它允许此操作具有O(1)的性能特征。当控制器数量增加时,对ElementAt
的调用的性能不会降低。
有了这个,您可以按如下方式编写装饰器:
class UserActivityControllerDecorator : IController
{
private readonly IController decoratee;
private readonly ILogger logger;
public UserActivityControllerDecorator(IController decoratee,
ILogger logger)
{
this.decoratee = decoratee;
this.logger = logger; }
public void Execute(RequestContext requestContext)
{
// do something before executing the controller
this.decoratee.Execute(requestContext);
// do something after executing the controller
}
}
我希望这是有道理的。