我对服务定位器和依赖注入的概念非常熟悉,但有一件事让我感到困惑,即为应用程序实现依赖注入,我们必须在开始时使用某种服务定位器.请考虑以下代码,假设我们有一些简单的DAL类:
public class UserProviderSimple : IUserProvider { public void CreateUser(User user) { //some code to user here } }
然后在Business Logig Layer中我们有一些使用IUserProvider的简单类,它使用构造函数注入注入:
public class UserServiceSimple : IUserService { public IUserProvider UserProvider { get; set; } public UserServiceSimple(IUserProvider userProvider) { UserProvider = userProvider; } public void CreateUser(User user) { UserProvider.CreateUser(user); } }
现在我们可能有几个这样的类,并且在任何地方都使用构造函数注入,但是在应用程序启动的主类中,所有这些类型都必须得到解决,因此我们必须使用服务定位器来解析所有这些类型,例如,在这里,我将创建一个单件服务定位器类来解决控制台应用程序启动时的所有依赖关系,如下所示:
public class ServiceLocator { private readonly UnityContainer _container; private static ServiceLocator _instance; public static ServiceLocator Instance() { if (_instance == null) { _instance = new ServiceLocator(); return _instance; } return _instance; } private ServiceLocator() { _container = new UnityContainer(); _container.RegisterType<IUserProvider,UserProviderSimple>(); _container.RegisterType<IUserService,UserServiceSimple>(); } public T Resolve<T>() { return _container.Resolve<T>(); } } class Program { private static IUserService _userService; private static void ConfigureDependencies() { _userService = ServiceLocator.Instance().Resolve<IUserService(); } static void Main(string[] args) { ConfigureDependencies(); } }
因此,似乎某种服务定位器总是在应用程序的开始使用,因此使用服务定位器是不可避免的,并且始终将其称为反模式权利是不正确的(除非它不在应用程序的根目录中使用) ?
解决方法
调用封装DI容器引导代码ServiceLocator的类没有任何内在错误,但您也可以将其称为Startup,Bootstrap或ContainerWrapper,它只是一个命名约定.
另一方面,作为设计模式的ServiceLocator通常被认为是反模式,因为它变成了对其余代码的硬依赖,并且使得更改和测试变得困难且不可预测.在您的代码中,它是Resolve< T>你想要远离的方法,以避免后果.
https://en.m.wikipedia.org/wiki/Service_locator_pattern
为了回答你的问题,通常需要一段代码来初始化DI容器,即使它是作为更大的DI框架本身的一部分而隐藏的,一些框架虽然允许从配置文件配置容器.希望能帮助到你!