如何在Application_BeginRequest中获取类的实例?

时间:2018-03-19 04:03:40

标签: .net asp.net-mvc dependency-injection castle-windsor

我刚刚开始使用Castle.Windsor有两个原因,其中一个原因就是不再使用静态类和单例模式。

我对DI的一般概念并不陌生,但对实现细节有点新鲜。我正在处理的那个:如何从Global.asax文件中的Application_BeginRequest方法中获取我注册的类的实例?我显然无法为此方法添加参数,并且我在此类的Application_Start方法中设置了容器,因此我不能创建一个构造函数来注入它。

这是一个边缘情况,我必须使用服务定位器模式或正确的方法是什么?

2 个答案:

答案 0 :(得分:1)

Application_BeginRequest是一种遗留的ASP.NET经典方法,它在MVC的上下文之外运行。提供实例的唯一方法是在Application_Start方法运行后保留容器的实例。

然而,MVC有更好的选择。如果您需要在每个请求中运行crosscutting concern,则应该global filter运行该逻辑。

public class MyFilter : IActionFilter
{
    private readonly ISomeDependency someDependency;

    public MyFilter(ISomeDependency someDependency)
    {
        this.someDependency = someDependency 
            ?? throw new ArgumentNullException(nameof(someDependency));
    }

    // Runs after action method
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
    }

    // Runs before action method
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        someDependency.DoSomething();
    }
}

用法

如果您可以将过滤器注册为单例,则只需在静态GlobalFilterCollection的应用程序启动时注册它。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters, IWindsorContainer container)
    {
        filters.Add(new MyFilter(container.Resolve<ISomeDependency>()));
        filters.Add(new HandleErrorAttribute());
    }
}

如果您有captive的依赖关系(例如DbContext),如果您注册为单身,则可以将工厂注入过滤器,或使用custom filter provider解析来自Castle Windsor容器的全局过滤器。

您可以阅读more details about filter providers here

  

注意:这真的只是冰山一角。您可以通过制作自定义属性来装饰您的操作并使用Reflection在您的过滤器中扫描它来控制过滤器将运行的操作(请参阅this example)。虽然MVC 排序使用ActionFilterAttribute扩展名进行此操作,但使用它并不是DI友好的。相反,制作符合DI的过滤器并制作attributes passive

答案 1 :(得分:0)

通常在Application_Start()中初始化容器。 只需在初始化容器的引用下创建一个静态变量,并在Application_BeginRequest()中使用它。