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

How to get instance of class in Application_BeginRequest?

我刚开始使用 Castle.Windsor 有几个原因,其中之一是避免同时使用静态 classes 和单例模式。

我对 DI 的一般概念并不陌生,但对实现细节有点陌生。我现在正在处理的问题是:如何从 Global.asax 文件的 Application_BeginRequest() 方法中获取我注册的 class 的实例?我显然不能向这个方法添加参数,我在这个 class 的 Application_Start() 方法中设置了容器,所以我不能创建一个构造函数来注入它。

这是我必须使用服务定位器模式的极端情况吗?或者执行此操作的正确方法是什么?

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

中使用它

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

之后保留容器实例

不过,MVC 有更好的选择。如果你有一个crosscutting concern that you need to run in each request, you should make a 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 (such as DbContext) if you registered as singleton, you can either inject a factory into your filter, or use a 从 Castle Windsor 容器解析全局过滤器的依赖项。

您可以阅读

NOTE: This is really just the tip of the iceberg. You could control which actions your filter will run on by making a custom attribute to decorate your actions with and using Reflection to scan for it in your filter (see ). While MVC sort of does this with its ActionFilterAttribute extension, it is not DI-friendly to use it. Instead, make DI-friendly filters and make the attributes passive.