我将在这里举一个例子来说明问题。请考虑以下课程:
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());
}
}
这个问题的第三个例子是不好的做法吗?如果是这样,为什么?我是通过这样做而失去了表现,还是因为这被认为是不好的做法还有其他原因?
答案 0 :(得分:3)
以这种方式使用依赖项解析程序意味着您正在使用the service locator anti-pattern。
您是否有任何理由认为创建MovieService
和UserService
会遇到性能问题?你在这些类的构造函数中做了什么重要的事情吗?如果是这样,那么你可能不应该这样做。在构造函数中,您几乎总是只接受依赖项并将它们存储在私有字段中。
如果由于某种原因,你仍然想要延迟加载,那么你可以创建这样的东西:
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(...)),
...);