asp.net core3.1 实战开发(autofact的使用替换框架的IOC实现AOP)

原有core 3.1内置了ioc容器和DI注入,有个缺点就算不能够实现AOP,所以使用第三方autofact来代替原有的容器

一:原有core 3.1的容器使用方法

配置服务

public void ConfigureServices(IServiceCollection services)
{
    services.AddSession();
    services.AddControllersWithViews();
    //只能构造函数注入--需要一个构造函数超集
    services.AddTransient<ITestServiceA, TestServiceA>();//瞬时
    services.AddSingleton<ITestServiceB, TestServiceB>();//单例
    services.AddScoped<ITestServiceC, TestServiceC>();//作用域单例--一次请求一个实例
    //作用域其实依赖于ServiceProvider(这个自身是根据请求的),跟多线程没关系
    services.AddTransient<ITestServiceD, TestServiceD>();
    services.AddTransient<ITestServiceE, TestServiceE>();
}

构造函数注入

public class SecondController : Controller
{
    private readonly ILogger<SecondController> _logger;
    private readonly ILoggerFactory _loggerFactory;
    private readonly ITestServiceA _iTestServiceA;
    private readonly ITestServiceB _iTestServiceB;
    private readonly ITestServiceC _iTestServiceC;
    private readonly ITestServiceD _iTestServiceD;
    private readonly ITestServiceE _iTestServiceE;
    private readonly IServiceProvider _iServiceProvider;
    /// <summary>
    /// 来自DI依赖注入---构造函数注入---构造A对象依赖B对象,自动初始化B对象传入
    /// 
    /// 有个容器,负责构造SecondController(反射)--反射构造函数--需要B--再构造B---然后再构造A
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="loggerFactory"></param>
    public SecondController(ILogger<SecondController> logger,
        ILoggerFactory loggerFactory
        , ITestServiceA testServiceA
        , ITestServiceB testServiceB
        , ITestServiceC testServiceC
        , ITestServiceD testServiceD
        , ITestServiceE testServiceE
        , IServiceProvider serviceProvider)
    //一次注入这么多,可能用不上,能不能我自己生成? 不建议,
    //1 大部分对象生成其实很快,且不占资源--特殊可以自己控制
    //2 对象生命周期不同,注入的是跟controller的,action是跟方法的
    {
        this._logger = logger;
        this._loggerFactory = loggerFactory;
        this._iTestServiceA = testServiceA;
        this._iTestServiceB = testServiceB;
        this._iTestServiceC = testServiceC;
        this._iTestServiceD = testServiceD;
        this._iTestServiceE = testServiceE;
        this._iServiceProvider = serviceProvider;
    }
    /// <summary>
    /// 纯属测试 毫无意义
    /// </summary>
    private static ITestServiceC _iTestServiceCStatic = null;
    private static ITestServiceB _iTestServiceBStatic = null;

    public IActionResult Index()
    {
        //ITestServiceA testServiceA = new TestServiceA();
        this._logger.LogWarning("This is SecondController Index");

        var c = this._iServiceProvider.GetService<ITestServiceC>();
        Console.WriteLine($"cc {object.ReferenceEquals(this._iTestServiceC, c)}");//T/F

        if (_iTestServiceCStatic == null)
        {
            _iTestServiceCStatic = _iTestServiceC;
        }
        else
        {
            Console.WriteLine($"C&C {object.ReferenceEquals(this._iTestServiceC, _iTestServiceCStatic)}");//两次不同的请求  //T/F
        }

        if (_iTestServiceBStatic == null)
        {
            _iTestServiceBStatic = _iTestServiceB;
        }
        else
        {
            Console.WriteLine($"B&B:{object.ReferenceEquals(this._iTestServiceB, _iTestServiceBStatic)}");//两次不同的请求  //T/F
        }


        this._iTestServiceA.Show();
        this._iTestServiceB.Show();
        this._iTestServiceC.Show();
        this._iTestServiceD.Show();
        this._iTestServiceE.Show();
        return View();
    }
}

二:autofac的容器使用方法

首先nuget引入:Autofac.Extensions.Depend
Profram中加入如下代码

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)//就是指定kestrel
                                 //.ConfigureLogging(loggingBuilder =>
                                 //    {
                                 //        loggingBuilder.AddLog4Net();//需要配置文件
                                 //    })
      .UseServiceProviderFactory(new AutofacServiceProviderFactory())//设置工厂来替换实例
      .ConfigureWebHostDefaults(webBuilder =>
      {
          webBuilder.UseStartup<Startup>();//靠Startup来串起来MVC
      });

Startup中加入如下代码

public void ConfigureContainer(ContainerBuilder containerBuilder)
 {
     //containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>().SingleInstance();
     containerBuilder.RegisterModule<CustomAutofacModule>();
 }

对应于CustomAutofacModule类

protected override void Load(ContainerBuilder containerBuilder)
        {
            var assembly = this.GetType().GetTypeInfo().Assembly;
            var builder = new ContainerBuilder();
            var manager = new ApplicationPartManager();
            manager.ApplicationParts.Add(new AssemblyPart(assembly));
            manager.FeatureProviders.Add(new ControllerFeatureProvider());
            var feature = new ControllerFeature();
            manager.PopulateFeature(feature);
            builder.RegisterType<ApplicationPartManager>().AsSelf().SingleInstance();
            builder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired();
            //containerBuilder.RegisterType<FirstController>().PropertiesAutowired();

            //containerBuilder.Register(c => new CustomAutofacAop());//允许使用AOP,注册
            containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>().SingleInstance().PropertiesAutowired();
            containerBuilder.RegisterType<TestServiceC>().As<ITestServiceC>();
            containerBuilder.RegisterType<TestServiceB>().As<ITestServiceB>();
            containerBuilder.RegisterType<TestServiceD>().As<ITestServiceD>();
            containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>();

            // 允许当前注册的这个服务实例使用Aop
            //containerBuilder.RegisterType<A>().As<IA>();//.EnableInterfaceInterceptors();

            //containerBuilder.Register<FirstController>();

            //containerBuilder.RegisterType<JDDbContext>().As<DbContext>();
            //containerBuilder.RegisterType<CategoryService>().As<ICategoryService>();

            //containerBuilder.RegisterType<UserServiceTest>().As<IUserServiceTest>();
        }

    }

autofactAOP的实现首先引入:Autofac.Extras.DynamicProxy

public class CustomAutofacAop : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine($"invocation.Methond={invocation.Method}");
        Console.WriteLine($"invocation.Arguments={string.Join(",", invocation.Arguments)}");

        invocation.Proceed(); //继续执行

        Console.WriteLine($"方法{invocation.Method}执行完成了");
    }
}

public interface IA
{
    void Show(int id, string name);
}

[Intercept(typeof(CustomAutofacAop))]
public class A : IA
{
    public void Show(int id, string name)
    {
        Console.WriteLine($"This is {id} _ {name}");
    }
}

配置文件实现

public class CustomAutofacModule : Module
{
    protected override void Load(ContainerBuilder containerBuilder)
    {
        #region 依赖于配置文件配置服务 
        // 实例化
        IConfigurationBuilder config = new ConfigurationBuilder();
        //指定配置文件  这里的默认配置文件的路径在根目录下,课根据实际情况调整
        config.AddJsonFile("autofac.json");
        // Register the ConfigurationModule with Autofac. 
        IConfigurationRoot configBuild = config.Build();
        //读取配置文件里配置需要注册的服务
        var module = new ConfigurationModule(configBuild);
        containerBuilder.RegisterModule(module);
        #endregion
    }
}

autofac.json 放在根目录如下:

{
    "defaultAssembly": "Microsoft.EntityFrameworkCore", // 抽象所在的程序集名称
    "components": [
      {
        "type": "Shop.EF.Model.shopdbContext,Shop.EF.Model", // 接口的实现类 全名称
        "services": [
          {
            "type": "Microsoft.EntityFrameworkCore.DbContext" // 接口的全名称
          }
        ],
        "instanceScope": "single-instance",
        "injectProperties": true
      },
      {
        "type": "Shop.Service.BaseService,Shop.Service", // 接口的实现类 全名称
        "services": [
          {
            "type": "Shop.Interface.IBaseService,Shop.Interface" // 接口的全名称
          }
        ],
        "instanceScope": "single-instance",
        "injectProperties": true
      },
      {
        "type": "Shop.Service.UserService,Shop.Service", // 接口的实现类 全名称
        "services": [
          {
            "type": "Shop.Interface.IUserService,Shop.Interface" // 接口的全名称
          }
        ],
        "instanceScope": "single-instance",
        "injectProperties": true
      },
      {
        "type": "Shop.Service.ProductService,Shop.Service", // 接口的实现类 全名称
        "services": [
          {
            "type": "Shop.Interface.IProductService,Shop.Interface" // 接口的全名称
          }
        ],
        "instanceScope": "single-instance",
        "injectProperties": true
      },
      {
        "type": "Shop.Service.OrderService,Shop.Service", // 接口的实现类 全名称
        "services": [
          {
            "type": "Shop.Interface.IOrderService,Shop.Interface" // 接口的全名称
          }
        ],
        "instanceScope": "single-instance",
        "injectProperties": true
      }
    ]
  }
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页