如何将依赖项注入到global.asax.cs中

38
如何将依赖注入到global.asax.cs,即MvcApplication类中?
之前我使用服务定位器(反)模式进行依赖注入,但在我的最新MVC应用程序中,我尝试通过使用IOC容器(具体来说是Unity.Mvc3,因为它自带IDependencyResolver的实现)和构造函数注入来遵循最佳实践建议。
到目前为止,一切都似乎相当简单,只有几个小问题,其中一个是在global.asax.cs中(另一个问题是针对自定义属性,但已经有一个关于这个问题的SO问题)。MvcApplication类中的HttpApplication事件处理程序如下:
Application_Start()
Application_EndRequest(object sender, EventArgs e)
Application_AcquireRequestState(object sender, EventArgs e)

可能需要外部依赖,例如对ILogService的依赖。那么我如何注入它们而不使用服务定位器(反)模式呢?

private static ILogService LogService
{
    get
    {
        return DependencyResolver.Current.GetService<ILogService>();
    }
}

非常感谢您提供的任何帮助和建议!


你好,有趣的问题!为什么不能在global.asax中的OnApplicationStarted方法中注入依赖项?如果应用程序无法启动,则您会意识到它,因为什么都不会工作... - user338195
2个回答

42

在global.asax.cs中的类是您的组合根,因此您不能(也不应该)从外部注入任何内容。

但是,MvcApplication类只有一个实例,因此如果您需要在其中一个方法中使用服务,只需将其声明为成员字段——例如:

public class MvcApplication : System.Web.HttpApplication
{
    private readonly ILogService log;

    public MvcApplication()
    {
        this.log = new MyLogService();
    }

    protected void Application_Start()
    {
        // ...

        this.log.Log("Application started");
    }
}

1
谢谢你的快速回复,马克。但是如果不能注入一个模拟实例(例如ILogService),那么你如何对方法进行单元测试呢? - magritte
4
我明白了,以下是翻译的结果:我不这样认为。组合根是谦卑对象的一个例子(http://xunitpatterns.com/Humble%20Object.html)。如果你需要在其中调用复杂逻辑,可以委托给另一个类来进行单元测试。 - Mark Seemann
3
你在你的博客文章中说,“DI容器只应该从组合根引用。所有其他模块都不应该引用容器。”这并不意味着只要在组合根内调用resolve就可以自由地使用它,也就是说,我的代码现在没问题吗?你例子中让我困扰的一件事是你对this.log = new MyLogService()的调用。既然我们在这时已经初始化了容器,那为什么不使用它呢?如果我们想要将ILogService换成另一个,我们只需要在一个地方更改它,即容器中。 - magritte
1
在我的回答中,我并没有假设您是否使用 DI 容器。如果您使用容器,可以从容器中解析而不是直接实例化它... - Mark Seemann
3
“‘MvcApplication’类只有一个实例”这个说法是错误的 - 每个并行处理的请求都有一个HttpApplication实例。请注意,对于每个正在运行的Web应用程序,仅在其初始创建时才调用“Application_Start”,而不是每次新创建实例时都调用。关于此的优秀博客文章:http://blog.andreloker.de/post/2008/05/HttpApplication-instances.aspx - blueling
显示剩余3条评论

0

你必须使用 AutofacConfig.Resolve<T>() 代替使用 DependencyResolver.Current.GetService<T>() 来获取你的服务,以避免出现错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接