【问题标题】:NInject and MVC 3 - Should I use DependencyResolver instead of [Inject] attribute?NInject 和 MVC 3 - 我应该使用 DependencyResolver 而不是 [Inject] 属性吗?
【发布时间】:2011-02-16 17:33:35
【问题描述】:

最近我转向 MVC 3 和 Ninject 2。在大部分代码中,我使用构造函数注入,但也有一些地方,我不得不使用 Inject 属性。 Ninject 2 注册了自己的IDepencyResolver 接口。我不喜欢 DependencyResolver 类成为 System.Web.Mvc 命名空间的一部分,因为它的功能与 MVC 并没有真正严格相关,但是现在,当它在那里时,我可以做

public SomeClass 
{
    public IUserService UserService { get; set; }

    public SomeClass()
    {
        UserService = DependencyResolver.Current.GetService<IUserService>();

而不是

public SomeClass 
{
    [Inject]
    public IUserService UserService { get; set; }

所以我不必在我的类中引用Ninject 命名空间。 DependencyResolver应该这样用吗?

【问题讨论】:

    标签: asp.net-mvc dependency-injection ninject ninject-2 ninject.web.mvc


    【解决方案1】:

    我只将属性注入用于类的正常工作不需要的依赖项,但如果用户设置它们可以添加一些功能。此类功能的示例是日志记录。因此,您可以拥有一个表示记录器的属性,用户可以在其中提供自己的实现,如果他不提供,则该类继续正常工作,但它根本不记录。

    对于其他一切,我使用构造函数注入。这样你就可以向消费者表明这个类对其他一些服务有必要的依赖。

    因此,要回答您关于属性注入的问题,我只需:

    public SomeClass 
    {
        public IUserService UserService { get; set; }
    
        public void SomeMethodWhichDoesntEnforceUserService()
        {
            if (UserService != null)
            {
                // Provide some additional functionality
            }
        }
    }
    

    如果没有用户服务,您的课程无法正常运行:

    public SomeClass 
    {
        private readonly IUserService _userService;
        public SomeClass(IUserService userService)
        {
            _userService = userService;
        }
    
        public void SomeMethodWhichRequiresTheService()
        {
            _userService.DoSomething();
        }
    }
    

    所以在这两种情况下都没有提及任何 DI 细节。这就是控制反转的意义所在。

    【讨论】:

    • 当 BaseClass 在构造函数中注入了 3 个接口并且 InheritedClass 有额外的 2 个接口时,你会怎么做。你用 5 个参数创建构造函数吗?
    • @LukLed,是的,但总的来说,我会尝试减少依赖项的数量。 5似乎很大。这意味着您的班级正在做太多事情,您可能应该考虑将其分成不同的班级。
    • 太多了? IPrincipal 被注入,IRepository 被注入,IApplicationCache 被注入 BaseClass。这些是基本项目,用于所有服务。我只是尝试尽可能多地注入,而不是直接引用。这使得构造函数中有很多参数。好的,我可以使用聚合服务来处理它。
    【解决方案2】:

    我要问的第一个问题是为什么不能将IUserService 的构造函数注入SomeClass?它可能表明设计存在问题。

    为避免直接引用DependencyResolver,您可以在 DI 框架上实现某种形式的服务定位器抽象,例如CommonServiceLocator,但正如this question 的答案所示,正确执行 DI 时不需要此类抽象。相反,您应该调整应用程序的设计。

    【讨论】:

    • DependencyResolver 是对DI 库的某种抽象。此类与 Ninject 无关。我在基类中使用Inject 属性,因为我不想向每个继承类的构造函数添加参数。我也遇到了一些循环引用问题。
    • 抱歉,我对 ninject 不太熟悉,但是如果您担心使用 ninject 引用污染代码,那么自动构造函数注入不是一种选择? kohari.org/2008/06/08/…
    • 构造函数注入是一种选择,但我不想拥有庞大的构造函数。行。我可能想太多了,其实没什么好想的。
    【解决方案3】:

    我相信 mvc3 的 ninject.web.mvc 版本现在支持对过滤器属性进行构造函数注入。你试过了吗?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 2011-12-29
    • 2018-06-10
    • 2012-04-02
    • 2023-03-15
    相关资源
    最近更新 更多