是否可以在应用程序启动时不使用服务定位器来实现依赖注入?

Myk*_*ych 6 c# dependency-injection inversion-of-control service-locator

我对服务定位器和依赖注入的概念非常熟悉,但有一件事让我感到困惑,即为应用程序实现依赖注入,我们必须在开始时使用某种服务定位器.请考虑以下代码,假设我们有一些简单的DAL类:

public class UserProviderSimple : IUserProvider
{
    public void CreateUser(User user)
    {
        //some code to user here
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可能有几个这样的类,并且在任何地方都使用构造函数注入,但是在应用程序启动的主类中,所有这些类型都必须得到解决,因此我们必须使用服务定位器来解析所有这些类型,例如,在这里,我将创建一个单件服务定位器类来解决控制台应用程序启动时的所有依赖关系,如下所示:

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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

因此,似乎某种服务定位器总是在应用程序的开始使用,因此使用服务定位器是不可避免的,并且始终将其称为反模式权利是不正确的(除非它不在应用程序的根目录中使用) ?

Ste*_*ven 5

您误解了服务定位器是什么.你确实理解它是一个反模式的部分,这很好,但你所缺少的是模式不是关于机制,而是它在应用程序中扮演的角色.换一种说法:

封装在Composition Root中的DI容器不是服务定位器 - 它是基础架构组件.


Eug*_*nko 3

调用封装 DI 容器引导代码的类本质上没有任何问题ServiceLocator,但您也可以将其称为StartupBootstrapContainerWrapper,这只是一种命名约定。

另一方面ServiceLocator,设计模式通常被认为是反模式,因为它成为其余代码的硬依赖,并使更改和测试变得困难且不可预测。在您的代码中Resolve<T>,您希望远离它以避免后果。

https://en.m.wikipedia.org/wiki/Service_locator_pattern

为了回答你的问题,在任何情况下通常都需要一段代码来初始化 DI 容器,即使它作为更大的 DI 框架本身的一部分对你隐藏,但有些框架也允许从配置文件配置你的容器。希望能帮助到你!