如何在MVC Core和AutoFac中使用Property Injection

时间:2018-05-23 04:04:24

标签: c# .net-core asp.net-core-mvc autofac property-injection

我可以在MVC Core中轻松使用Constructor Parameter Injection。但不支持Property Injection。我尝试使用AutoFac但也失败了 那么如何在MVC Core中使用Property Injection 以下是AutoFac的代码

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); 

2 个答案:

答案 0 :(得分:2)

在dotnet核心中,您需要进行以下更改才能使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());
}

执行此操作后 - 您的控制器应自动获取自动装配的属性。

答案 1 :(得分:0)

属性注入需要一些其他设置。让我们假设您有这样的类层次结构:

    public class HomeController 
    {
        public ITest Test {get; set;}            
    }    
    public class Test : ITest
    {
        public IRepository Repository {get;set;}    
    }
    public class Repository: IRepository
    {
    }

要做的第一件事是将ConfigureServices(IServiceCollection services)的返回类型更改为IServiceProvider,并使用'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容器中注册类。与“控制器”相比,“服务类”的属性注入所需的动作更少。 要为 服务类 设置属性注入,您只需要:

  1. 在容器中注册类型: builder.RegisterType<Repository>().As<IRepository>();
  2. 您将通过其注入依赖项的寄存器类型 具有 PropertiesAutowired()的属性: builder.RegisterType<Test>.As<ITest>().PropertiesAutowired()

要为 控制器 设置属性注入,您还需要一些步骤:

  1. AddControllersAsServices()上执行services.AddMvc()
  2. 针对所有控制器的调用PropertiesAutowired()的控制器的注册器DI:

    //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());
}