如何使用Simple Injector装饰ASP.NET MVC控制器 [英] How to decorate an ASP.NET MVC controller with Simple Injector

查看:44
本文介绍了如何使用Simple Injector装饰ASP.NET MVC控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对我的MVC控制器应用一些横切关注点.目前,这是通过抽象基类实现的,但是随着我们重构更多代码库以利用依赖注入的优势,我想知道这是否是简单注入器可以通过其装饰或拦截功能为我提供帮助的地方

I'd like to apply some cross-cutting concerns to my MVC controllers. At the moment, this is implemented through an abstract base class, but as we are refactoring more of the code base to take advantage of dependency injection, I'm wondering if this is something Simple Injector can help me with through its decoration or interception facilities.

因此,我尝试创建一个非常基本的装饰器:

So I've attempted to create a pretty basic decorator:

public class ControllerDecorator : IController
{
    private readonly IController _controller;

    public ControllerDecorator(IController controller)
    {
        _controller = controller;
    }

    public void Execute(RequestContext requestContext)
    {
        // Do something of a cross-cutting nature here...

        _controller.Execute(requestContext);
    }
}

在我的创作根目录中:container.RegisterDecorator<IController, ControllerDecorator>()

And in my composition root: container.RegisterDecorator<IController, ControllerDecorator>()

但是,装饰器的Execute方法中的代码似乎从未被调用过.是因为MVC框架直接解析我的控制器类,而不是通过IController吗?在这种情况下,我该怎么办?我在这里想念什么?

However, the code in my decorator's Execute method doesn't seem to ever get called. Is it because the MVC framework directly resolves my controller classes instead of going through IController? In that case, what can I do? What am I missing here?

推荐答案

在默认配置中,您不能将装饰器应用于控制器.原因是MVC的DefaultControllerFactory根据其具体类型请求控制器.因为它请求具体类型,所以Simple Injector无法应用装饰器.必须假定调用者需要此具体类型,并因此必须返回此确切类型(或子类型).

In the default configuration, you can't apply decorators to controllers. The reason for this is that MVC's DefaultControllerFactory requests controllers by their concrete type. Because it requests a concrete type, Simple Injector is unable to apply a decorator; it has to assume that the caller needs this concrete type and has to therefore return this exact type (or a sub type).

要解决此问题,您将必须使用自定义项替换默认的DefaultControllerFactory:

To fix this, you will have to replace the default DefaultControllerFactory with a custom one:

public class SimpleInjectorControllerFactory : DefaultControllerFactory {
    public IDictionary<Type, InstanceProducer> Producers { get; set; }
    protected override IController GetControllerInstance(RequestContext rc, Type type) {
        return (IController)this.Producers[type].GetInstance();
    }
}

接下来,在引导程序中,您必须将对RegisterMvcControllers的调用替换为以下内容:

Next, in your bootstrapper, you'll have to replace the call to RegisterMvcControllers with the following:

var controllerTypes = SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
    container, Assembly.GetExecutingAssembly());

var controllerProducers = controllerTypes
    .ToDictionary(type => type, type => CreateControllerProducer(container, type));

// Verify after creating the controller producers.
container.Verify();

ControllerBuilder.Current.SetControllerFactory(
    new SimpleInjectorControllerFactory { Producers = controllerProducers });

CreateControllerProducer方法如下所示:

private static InstanceProducer CreateControllerProducer(Container c, Type type) {
    var producer = Lifestyle.Transient.CreateProducer(typeof(IController), type, c);
    producer.Registration.SuppressDiagnosticWarning(
        DiagnosticType.DisposableTransientComponent,
        "MVC disposes the controller when the web request ends.");
    return producer;
}

关键部分是typeof(IController)提供了对CreateProducer的调用;这使Simple Injector可以为IController应用装饰器.

The crucial part is that the call to CreateProducer is supplied with typeof(IController); this allows Simple Injector to apply a decorator for IController.

就是这样;现在您可以为IController注册装饰器.

This is it; now you can register your decorator for IController.

不过,有一个警告:使用Web API和新的ASP.NET核心,不可能将装饰器应用于控制器.这两个框架都期望有具体的类型.如果包装了真正的控制器,它们将损坏.使用这些框架来装饰控制器的首选方法是通过OWIN管道.因此,此答案仅适用于MVC 3、4和5.

One warning though: with both Web API and the new ASP.NET core it is impossible to apply decorators to controllers. Both frameworks expect concrete types; they will break if you wrap the real controller. The preferred way with those frameworks to decorate controllers is through the OWIN pipeline. So this answer solely works with MVC 3, 4 and 5.

这篇关于如何使用Simple Injector装饰ASP.NET MVC控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆