Области неявных запросов локатора сервисов - PullRequest
1 голос
/ 12 июля 2020

Я создал небольшой локатор служб, который буду использовать в ActionFilterAttributes и IHttpModules. На момент написания я использую простой инжектор, но хочу сделать его контейнерной агности c. Идея состоит в том, чтобы позволить потребителям моего фреймворка вводить дополнительную конфигурацию в мои классы, например:

container.RegisterInstance<IConfiguration>(() => new CustomConfiguration());

Ниже мой текущий черновик. Пожалуйста, не стесняйтесь предлагать любые улучшения. На ум пришло то, насколько хорошо он будет относиться к услуге с ограниченным образом жизни. Например, если я запрашиваю службу в фильтре OnActionExecuting, поймет ли контейнер, что служба запрашивается в области веб-запроса, или мне нужно явно создать область? Конфигурация будет одинарной, так что это не будет проблемой с указанной зависимостью c, просто спрашиваю из любопытства.

public class ServiceLocator
{
    public static T GetService<T>()
    {
        return (T)GetDependencyScope().GetService(typeof(T));
    }

    private static IDependencyScope GetDependencyScope()
    {
        if (HttpContext.Current.Items["MS_HttpRequestMessage"] is HttpRequestMessage httpRequestMessage)
        {
            return httpRequestMessage.GetDependencyScope();
        }
        return GlobalConfiguration.Configuration.DependencyResolver;
    }
}

1 Ответ

0 голосов
/ 15 июля 2020

Я бы внедрил экземпляр IServiceProvider в контейнер Io C, который вы используете.

В этом примере показано, как это сделать с помощью Simple Injector:

public class SimpleInjectorServiceProvider : IServiceProvider {

    private readonly Container container;

    public SimpleInjectorServiceProvider(Container container) {
        this.container = container;
    }

    public object GetService(Type t)
    {
        return container.GetInstance(t);   
    }
    //all other useful methods are provided by Extensions Methods in Microsoft.Extensions.DependencyInjection.Abstractions.dll

}

//Register your dependencies here
public static void RegisterContainer(Container container) {
   container.Register(typeof(IServiceProvider),() => new SimpleInjectorServiceProvider(container), Lifestyle.Singleton);
   //your dependencies
}

//use your service locator
public class AClass {
     private readonly IServiceProvider serviceProvider;
     public AClass(IServiceProvider serviceProvider) {
         this.serviceProvider = serviceProvider;
     }

     public object AMethod() {
          AType myDependency = serviceProvider.GetService<AType>();
         ...
     }
}

при переключении на другая система DI, вам просто нужно создать еще одну реализацию IServiceProvider

public class LightInjectServiceProvider : IServiceProvider {

    private readonly ServiceContainer container;

    public LightInjectServiceProvider(ServiceContainer container) {
        this.container = container;
    }

    public object GetService(Type t)
    {
        return container.GetInstance(t);   
    }
    //all other useful methods are provided by Extensions Methods in Microsoft.Extensions.DependencyInjection.Abstractions.dll

}

, а поскольку «потребители» знают только интерфейс IServiceProvider, вам не нужно никаких других изменений

...