C# autofac 在Net6中的使用

时间:2023-03-26 10:54:54

十年河东,十年河西,莫欺少年穷。

学无止境,精益求精。

准备如下工作:

新建一个Net6  webApi项目,并在该项目中引入:

C# autofac 在Net6中的使用

 

 新建类库MyInterface 和 MyService,项目构造如下

C# autofac 在Net6中的使用

 

 接口如下:

/// <summary>
    /// 动物接口
    /// </summary>
    public interface IAnimal
    {
        void say(); 
    }

实现类如下:

namespace MyService
{ 

    public class DogService : IAnimal
    {
        public void say()
        {
            Console.WriteLine("汪汪汪");
        }
    }

    public class CatService : IAnimal
    {
        public void say()
        {
            Console.WriteLine("喵喵喵");
        }
    }

    public class PigService : IAnimal
    {
        public void say()
        {
            Console.WriteLine("哼哼哼");
        }
    }
     
}

View Code

1、在webApi中引入autofac,并进行接口和实现类注入

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
    containerBuilder.RegisterType<DogService>().As<IAnimal>();
    containerBuilder.RegisterType<CatService>().As<IAnimal>();
    containerBuilder.RegisterType<PigService>().As<IAnimal>();
});

View Code

C# autofac 在Net6中的使用

 

 2、在控制器中通过构造函数注入

namespace WebAppAutofac.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class HomeController : ControllerBase
    {
        private readonly IAnimal Animal;
        private readonly IEnumerable<IAnimal> Animals; 

        public HomeController( IAnimal animal, IEnumerable<IAnimal> animals,IServiceProvider provider,IComponentContext context)
        {
            Animal = animal;
            Animals = animals;
            //
            var MyAnimal_1 = provider.GetService<IAnimal>();
            var MyAnimal_2 = context.Resolve<IAnimal>();
            //// 
        }

        [HttpGet]
        public ActionResult get()
        {
            Animal.say();
            Console.WriteLine($"实现类的个数为:" + Animals.Count());
            
            return Ok();
        }
    }
}

3、单抽象多继承的处理

项目中,动物接口由猫、狗、猪三个实现类继承,因此,上述代码构建的对象时最后一个注入的实现类对象,因此,我们有必要对单抽象多继承进行处理

关于单抽象多继承问题,可参考上篇博客:C# Autofac 构造函数注入,属性注入,方法注入

修改Program.cs注册autofac方法如下:

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
    containerBuilder.RegisterType<DogService>().Keyed<IAnimal>("dog");
    containerBuilder.RegisterType<CatService>().Keyed<IAnimal>("cat");
    containerBuilder.RegisterType<PigService>().Keyed<IAnimal>("pig"); 
});

控制器注入如下:

using Autofac;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MyInterface;

namespace WebAppAutofac.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class HomeController : ControllerBase
    {
        //
        private readonly IAnimal dog;
        private readonly IAnimal cat;
        private readonly IAnimal pig;

        public HomeController(IServiceProvider provider,IComponentContext context)
        { 
            //
            var s = provider.GetService<IAnimal>();
            ////
            dog = context.ResolveKeyed<IAnimal>("dog");
            cat = context.ResolveKeyed<IAnimal>("cat");
            pig = context.ResolveKeyed<IAnimal>("pig");
        }

        [HttpGet]
        public ActionResult get()
        { 
            dog.say();
            cat.say();
            pig.say();
            return Ok();
        }
    }
}

4、属性注入

由于本案例采用的是单抽象多继承,因此代码直接使用Keyed标识

修改Program.cs注册autofac方法如下

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{ 
    containerBuilder.RegisterType<DogService>().Keyed<IAnimal>("dog");
    containerBuilder.RegisterType<CatService>().Keyed<IAnimal>("cat");
    containerBuilder.RegisterType<PigService>().Keyed<IAnimal>("pig");
    //使继承自ControllerBase的控制器支持属性注入且排除掉ControllerBase自己
    var ControllerBaseType = typeof(ControllerBase);
    containerBuilder.RegisterAssemblyTypes(typeof(Program).Assembly).Where(A => ControllerBaseType.IsAssignableFrom(A) && A != ControllerBaseType).PropertiesAutowired();
});

//修改微软默认设置
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

注意红色的两段代码

C# autofac 在Net6中的使用

 

 控制器代码如下:

using Autofac;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MyInterface;

namespace WebAppAutofac.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class HomeController : ControllerBase
    {
        //
        public IAnimal dog { get; set; }
        public  IAnimal cat { get; set; }
        public IAnimal pig { get; set; }

        public HomeController(IServiceProvider provider, IComponentContext context)
        {
            //dog = provider.GetService<IAnimal>();
            dog = context.ResolveKeyed<IAnimal>("dog");
            cat = context.ResolveKeyed<IAnimal>("cat");
            pig = context.ResolveKeyed<IAnimal>("pig");
        }

        [HttpGet]
        public ActionResult get()
        { 
            dog.say();
            cat.say();
            pig.say();
            return Ok();
        }
    }
}

over

@陈大六的波尔卡