使用Dependency Resolver是一种不好的做法吗?

时间:2017-07-12 21:41:08

标签: c# asp.net-mvc design-patterns dependency-injection

我将在这里举一个例子来说明问题。请考虑以下课程:

public class MovieController : Controller
{
    private readonly IMovieService _movieService;
    private readonly IUserService _userService;

    public MovieController(IMovieService movieService, IUserService userService)
    {
        _movieService = movieService;
        _userService = userService;
    }

    public ViewModel GetMovies()
    {
        return View("Movies", _movieService.GetMovies());
    }

    public ViewModel GetAuthors()
    {
        return View("Authors", _userService.GetAuthors());
    }
}

通过上面的示例,无论何时创建MovieController,它都将创建两个服务。每个服务都需要在构造函数中使用其服务和存储库。所以,实际上,每次调用MovieController时我都可能会创建一些类。出于这个原因,我想实现Lazy加载,因为我相信它会提高性能。因此,请考虑下一堂课:

public class MovieController : Controller
{
    private readonly IMovieService _movieService;
    private readonly IUserService _userService;

    private MovieService 
    {
        get 
        {
            if (_movieService == null) _movieService = new MovieService();
            return _movieService;
        }
    }

    private UserService 
    {
        get 
        {
            if (_userService == null) _userService = new UserService();
            return _userService;
        }
    }

    public MovieController() { }

    public ViewModel GetMovies()
    {
        return View("Movies", MovieService.GetMovies());
    }

    public ViewModel GetAuthors()
    {
        return View("Authors", UserService.GetAuthors());
    }
}

上述例子的问题是我丢失了DI。现在我理解DI的好处,我非常想保留它,因此,我想出了以下示例:

public class MovieController : Controller
{
    private readonly IMovieService _movieService;
    private readonly IUserService _userService;

    private MovieService 
    {
        get 
        {
            if (_movieService == null) _movieService = DependencyResolver.Current.GetService(typeof(IMovieService));
            return _movieService;
        }
    }

    private UserService 
    {
        get 
        {
            if (_userService == null) _userService = DependencyResolver.Current.GetService(typeof(IUserService));
            return _userService;
        }
    }

    public MovieController() { }

    public ViewModel GetMovies()
    {
        return View("Movies", MovieService.GetMovies());
    }

    public ViewModel GetAuthors()
    {
        return View("Authors", UserService.GetAuthors());
    }
}

这个问题的第三个例子是不好的做法吗?如果是这样,为什么?我是通过这样做而失去了表现,还是因为这被认为是不好的做法还有其他原因?

1 个答案:

答案 0 :(得分:3)

以这种方式使用依赖项解析程序意味着您正在使用the service locator anti-pattern

您是否有任何理由认为创建MovieServiceUserService会遇到性能问题?你在这些类的构造函数中做了什么重要的事情吗?如果是这样,那么你可能不应该这样做。在构造函数中,您几乎总是只接受依赖项并将它们存储在私有字段中。

如果由于某种原因,你仍然想要延迟加载,那么你可以创建这样的东西:

public class LazyMovieService : IMovieService
{
    private readonly Lazy<IMovieService> lazyInstance;

    public LazyMovieService(Func<IMovieService> instanceFactory)
    {
        lazyInstance = new Lazy<IMovieService>(instanceFactory);
    }
    public string[] GetMovies()
    {
        return lazyInstance.Value.GetMovies();
    }
}

此类允许您在代码中使用第一个代码示例,同时仍然可以懒惰地加载您的服务。

Composition Root中,您只需执行以下操作:

var controller =
    new MovieController(
        new LazyMovieService(() => new MyOriginalMovieService(...)),
        ...);