我刚刚开始使用Castle.Windsor有两个原因,其中一个原因就是不再使用静态类和单例模式。
我对DI的一般概念并不陌生,但对实现细节有点新鲜。我正在处理的那个:如何从Global.asax文件中的Application_BeginRequest方法中获取我注册的类的实例?我显然无法为此方法添加参数,并且我在此类的Application_Start方法中设置了容器,因此我不能创建一个构造函数来注入它。
这是一个边缘情况,我必须使用服务定位器模式或正确的方法是什么?
答案 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()中使用它。