2

最近我转向 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这样使用吗?

4

3 回答 3

5

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

对于其他一切,我使用构造函数注入。通过这种方式,您可以向消费者表明该类对某些其他服务具有必需的依赖关系。

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

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 细节。这就是控制反转的全部意义所在。

于 2011-02-16T17:59:31.873 回答
1

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

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

于 2011-02-16T17:48:24.417 回答
0

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

于 2011-02-16T18:01:00.420 回答