2016-06-06 2 views
0

В течение ConfigureServices Я настраиваю ряд сервисов (это работает). В том же методе я пытаюсь настроить собственный поставщик файлов (для Razor). Это выглядит следующим образом:Запросить экземпляр в ConfigureServices

services.AddMvc() 
     .AddRazorOptions(options => 
     { 
      options.FileProvider = new CustomFileProvider(???); 
     }); 

CustomFileProvider имеет несколько зависимостей (которые все настроено), но как я могу спросить DI дать мне экземпляр CustomFileProvider сразу после того, все службы были настроены?

Из того, что я вижу, DI только вводит в конструкторы, но в моем случае мне нужно «пожалуйста, дайте мне экземпляр CustomFileProvider здесь».

+0

Вы не можете разрешить в ConfigureServices, поскольку контейнер создается после вызова 'ConfigureServices' и до вызова' Configure'. Если у поставщика нет сложной структуры зависимостей, вы должны ввести их вручную. – Tseng

ответ

2

Если вы хотите разрешать услуги из контейнера при настройке некоторых параметров, вам необходимо использовать инфраструктуру IConfigureOptions<TOption>, которую большинство MVC использует для настройки параметров по умолчанию. См., Например, RazorViewEngineOptionsSetup.

Во-первых, добавить необходимые Вам услуги в коллекции:

services.AddSingleton<IDependency1, Dependency1>(); 
services.AddSingleton<IDependency2, Dependency2>(); 

Затем реализовать класс установки:

public class CustomFileProviderRazorViewEngineOptionsSetup : ConfigureOptions<RazorViewEngineOptions> 
{ 
    public CustomFileProviderRazorViewEngineOptionsSetup(IServiceProvider serviceProvider) 
     : base(options => ConfigureRazor(options, serviceProvider)) 
    { 
    } 

    private static void ConfigureRazor(RazorViewEngineOptions options, IServiceProvider serviceProvider) 
    { 
     // Alternative 1 - Resolve each service and new up the instance. 
     var dependency1 = serviceProvider.GetService<IDependency1>(); 
     var dependency2 = serviceProvider.GetService<IDependency2>(); 

     options.FileProviders.Add(new CustomFileProvider(dependency1, dependency2)); 

     // Alternative 2 - Same as alternative 1, but with moar magic ;) 
     options.FileProviders.Add(ActivatorUtilities.CreateInstance<CustomFileProvider>(serviceProvider)); 

     // Alternative 3 - Just resolve CustomFileProvider from the service provider. 
     // This requires it to be registered first, of course. 
     options.FileProviders.Add(serviceProvider.GetService<CustomFileProvider>()); 
    } 
} 

Это разрешенное из контейнера, так что это позволит вам введите IServiceProvider, который может быть снова использован для разрешения необходимых вам услуг. Вы можете при необходимости добавить CustomFileProvider в контейнер и решить, что непосредственно вместо этого, как и в альтернативной 3.

Наконец, добавьте класс установки в коллекцию услуг:

services.TryAddEnumerable(
    ServiceDescriptor.Transient< 
     IConfigureOptions<RazorViewEngineOptions>, 
     CustomFileProviderRazorViewEngineOptionsSetup>()); 

Это добавит настройки к параметрам builder, что означает, что он будет работать с другими зарегистрированными экземплярами IConfigureOptions<RazorViewEngineOptions> для настройки объекта опций.

+0

+1. Вы даже можете использовать 'options.FileProviders.Add (ActivatorUtilities.CreateInstance (serviceProvider, typeof (CustomFileProvider))), чтобы немного упростить создание экземпляра. – Pinpoint

+0

Да. Добавлено несколько альтернатив :) – khellang

Смежные вопросы