Как использовать Property Injection в MVC Core и AutoFac
Я могу легко использовать Constructor Parameter Injection в MVC Core. Но свойство Injection не поддерживается. Я пытаюсь использовать AutoFac, но тоже не получается.
Итак, как использовать Property Injection в MVC Core.
Вот код с автофаком
services.AddMvc();
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Test2>().As<ITest>();
builder.RegisterType<HomeController>().PropertiesAutowired();
builder.Populate(services);
var container = builder.Build();
//The following code works
HomeController test2 = container.Resolve<HomeController>();
return new AutofacServiceProvider(container);
1 ответ
В ядре dotnet для работы Autofac необходимо внести следующие изменения: Добавить общедоступный Autofac IContainer
в вашем приложении Startup.cs
public IContainer ApplicationContainer { get; private set; }
+ Изменить ConfigureServices
в Startup.cs
возвращать IServiceProvider
, сделайте все свои регистрации, заполните сервисы фреймворка в вашем контейнере, используя builder.Populat(services);
, Обратите внимание, что вам не нужно делать builder.RegisterType<HomeController>().PropertiesAutowired();
public IServiceProvider ConfigureServices(IServiceCollection services)
{
builder.Populate(services);
ApplicationContainer = container;
return new AutofacServiceProvider(ApplicationContainer);
}
Вам также необходимо убедиться, что вы удалили контейнер для приложения, остановленного, выполнив это в своем Configure
метод.
public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime)
{
app.UseMvc();
appLifetime.ApplicationStopped.Register(() => ApplicationContainer.Dispose());
}
После того как вы это сделаете - ваши контроллеры должны автоматически получить свойства автоматически подключенными.
Внедрение свойства требует дополнительной настройки. Предположим, в вашем случае у нас есть эта иерархия классов:
public class HomeController
{
public ITest Test {get; set;}
}
public class Test : ITest
{
public IRepository Repository {get;set;}
}
public class Repository: IRepository
{
}
Прежде всего нужно изменить тип возвращаемого значения на IServiceProvider для ConfigureServices(IServiceCollection services)
и создание нового контейнера с использованием Populate
метод из метода 'Autofac.Extensions.DependencyInjection' для возврата AutofacServiceProvider
Новый метод ConfigureServices:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
ContainerBuilder builder = new ContainerBuilder();
builder.Populate(services);//Autofac.Extensions.DependencyInjection
/*Here we are going to register services for DI*/
return new AutofacServiceProvider(builder.Build());
}
Следующим шагом является регистрация классов в DI-контейнере. Внедрение свойств для "классов обслуживания" требует меньше действий, чем для "контроллеров". Чтобы настроить внедрение свойств для классов обслуживания, вам просто необходимо:
- Тип регистрации в контейнере:
builder.RegisterType<Repository>().As<IRepository>();
- Зарегистрируйте тип, в который вы собираетесь внедрить зависимости через свойства с помощью PropertiesAutowired ():
builder.RegisterType<Test>.As<ITest>().PropertiesAutowired()
Чтобы настроить внедрение свойства для контроллеров, вам нужно сделать еще несколько шагов:
- казнить
AddControllersAsServices()
наservices.AddMvc()
Regiser DI для контроллеров с вызовом
PropertiesAutowired()
для всех контроллеров://in case you just need to allow registration for several specific controllers change this line var controllersTypesInAssembly = typeof(Startup).Assembly .GetExportedTypes() .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray(); builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
В результате вот ConfigureServices() для предопределенной иерархии:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddControllersAsServices();
ContainerBuilder builder = new ContainerBuilder();
builder.Populate(services);//Autofac.Extensions.DependencyInjection
builder.RegisterType<Repository>().As<IRepository>()
.InstancePerLifetimeScope();
var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
builder.RegisterType<Test>().As<ITest>().PropertiesAutowired();
return new AutofacServiceProvider(builder.Build());
}