← Назад к вопросам

Что такое Service Locator?

1.6 Junior🔥 201 комментариев
#ASP.NET и Web API

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Service Locator?

Service Locator — это паттерн проектирования, который предоставляет центральный реестр для получения экземпляров сервисов. Вместо инъекции зависимостей (Dependency Injection), класс сам запрашивает нужный сервис из локатора.

Service Locator паттерн

// Центральный реестр сервисов
public class ServiceLocator
{
    private static Dictionary<Type, object> _services = new();
    
    public static void Register<T>(T instance)
    {
        _services[typeof(T)] = instance;
    }
    
    public static T GetService<T>()
    {
        return (T)_services[typeof(T)];
    }
}

// Использование
public class UserService
{
    private ILogger _logger = ServiceLocator.GetService<ILogger>();  // поиск в локаторе
}

Инициализация

static void Main()
{
    // Регистрируем сервисы в локаторе
    ServiceLocator.Register<ILogger>(new ConsoleLogger());
    ServiceLocator.Register<IUserRepository>(new UserRepository());
    
    // Теперь классы могут получать их
    var userService = new UserService();
}

Проблемы Service Locator

1. Скрытые зависимости

public class UserService
{
    public UserService()  // Конструктор НЕ показывает зависимости
    {
        _logger = ServiceLocator.GetService<ILogger>();  // спрятано внутри
    }
}

// Трудно понять, что нужно сервису!

2. Сложнее тестировать

[Test]
public void TestUserService()
{
    // Нужно настроить весь Service Locator перед тестом
    ServiceLocator.Register<ILogger>(new MockLogger());
    
    var service = new UserService();
    service.DoSomething();
    
    // Vs DI — просто передаешь mock в конструктор
}

3. Runtime ошибки вместо compile-time

// Service Locator — ошибка при запуске
var logger = ServiceLocator.GetService<ILogger>();  // может быть null!

// DI — ошибка при компиляции
public UserService(ILogger logger)  // если забыл регистрировать — падает на старте
{
    _logger = logger;
}

Правильный подход — Dependency Injection

// ✅ DI: зависимости в конструкторе
public class UserService
{
    private readonly ILogger _logger;
    private readonly IUserRepository _repo;
    
    public UserService(ILogger logger, IUserRepository repo)  // явные зависимости
    {
        _logger = logger;
        _repo = repo;
    }
}

// Регистрация в контейнере
var services = new ServiceCollection();
services.AddScoped<ILogger, ConsoleLogger>();
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<UserService>();

var serviceProvider = services.BuildServiceProvider();
var userService = serviceProvider.GetRequiredService<UserService>();

Когда Service Locator может быть полезен

  1. Legacy код — если нельзя переделать на DI
  2. Factory паттерн — когда не знаешь тип на время компиляции
  3. Плагины — динамическая загрузка модулей
// Factory с Service Locator
public class PaymentProviderFactory
{
    public IPaymentProvider CreateProvider(string type)
    {
        // Динамически получаем нужный провайдер
        var providerType = Type.GetType($"Company.Payment.{type}Provider");
        return ServiceLocator.GetService(providerType) as IPaymentProvider;
    }
}

Service Locator vs Dependency Injection

АспектService LocatorDependency Injection
Видимость зависимостейСкрытаЯвная (конструктор)
ТестированиеСложнееПроще (передаешь моки)
Type SafetyRuntimeCompile-time
СложностьМеньшеБольше
МасштабируемостьПлохоХорошо

ASP.NET Core — встроенный DI контейнер

public class Startup
{
    public void ConfigureServices(IServiceCollection services)  // регистрация
    {
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddScoped<UserService>();
    }
}

public class UserController : ControllerBase
{
    private readonly UserService _service;  // инъекция через конструктор
    
    public UserController(UserService service)
    {
        _service = service;  // ASP.NET автоматически создал и передал
    }
}

Итог

Service Locator — это анти-паттерн в современном .NET. Используй Dependency Injection (встроенный контейнер в ASP.NET Core) — это лучше для тестирования, масштабируемости и читаемости кода.

Что такое Service Locator? | PrepBro