Core 3.1 had the IOC container and DI injection built in, but it had the disadvantage of using third-party Autofact instead of AOP

I: Original core 3.1 container usage method

public void ConfigureServices(IServiceCollection services)
{
    services.AddSession();
    services.AddControllersWithViews();
    Constructor injection only -- a constructor superset is required
    services.AddTransient<ITestServiceA, TestServiceA>();/ / the instantaneous
    services.AddSingleton<ITestServiceB, TestServiceB>();/ / the singleton
    services.AddScoped<ITestServiceC, TestServiceC>();// Scoped singleton -- request one instance at a time
    // The scope actually depends on ServiceProvider (which itself is request-dependent) and has nothing to do with multithreading
    services.AddTransient<ITestServiceD, TestServiceD>();
    services.AddTransient<ITestServiceE, TestServiceE>();
}
Copy the code
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>
    ///From DI dependency injection -- constructor injection -- construct A object to depend on B object, automatically initialize B object incoming
    /// 
    ///There's A container that builds the SecondController(Reflection)-- the reflection constructor -- takes B-- builds B-- builds A
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="loggerFactory"></param>
    public SecondController(ILogger
       
         logger, ILoggerFactory loggerFactory , ITestServiceA testServiceA , ITestServiceB testServiceB , ITestServiceC testServiceC , ITestServiceD testServiceD , ITestServiceE testServiceE , IServiceProvider serviceProvider
       )
    // If you want to inject so many bytes, you may not need to use them. It is not recommended,
    //1 Most object generation is actually very fast and does not take up resources
    //2 Object life cycle is different, injection is controller, action is method
    {
        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>
    ///There's no point in testing
    /// </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)}");// Two different requests //T/F
        }

        if (_iTestServiceBStatic == null)
        {
            _iTestServiceBStatic = _iTestServiceB;
        }
        else
        {
            Console.WriteLine($" B&B:{object.ReferenceEquals(this._iTestServiceB, _iTestServiceBStatic)}");// Two different requests //T/F
        }


        this._iTestServiceA.Show();
        this._iTestServiceB.Show();
        this._iTestServiceC.Show();
        this._iTestServiceD.Show();
        this._iTestServiceE.Show();
        returnView(); }}Copy the code

Two: autoFAC container usage method

First introduced nuget: Autofac. Extensions. Depend

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)// specify kestrel
                                 //.ConfigureLogging(loggingBuilder =>
                                 / / {
                                 // loggingBuilder.AddLog4Net(); // A configuration file is required
                                 / /})
      .UseServiceProviderFactory(new AutofacServiceProviderFactory())// Set up the factory to replace the instance
      .ConfigureWebHostDefaults(webBuilder =>
      {
          webBuilder.UseStartup<Startup>();// use Startup to string MVC
      });
Copy the code

Add the following code to Startup

public void ConfigureContainer(ContainerBuilder containerBuilder)
 {
     //containerBuilder.RegisterType<TestServiceE>().As<ITestServiceE>().SingleInstance();
     containerBuilder.RegisterModule<CustomAutofacModule>();
 }
Copy the code
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()); // Allow the use of AOP, register
            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>();

            // Allow the currently registered service instance to use Aop
            //containerBuilder.RegisterType().As
       
        (); //.EnableInterfaceInterceptors();
       

            //containerBuilder.Register<FirstController>();

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

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

AutofactAOP the implementation of the first to introduce: 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(); // Continue execution

        Console.WriteLine($" method{invocation.Method}Execution done."); }}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}"); }}Copy the code

Configuration file implementation

public class CustomAutofacModule : Module
{
    protected override void Load(ContainerBuilder containerBuilder)
    {
        #regionDepend on the configuration file to configure the service
        / / instantiate
        IConfigurationBuilder config = new ConfigurationBuilder();
        The path of the default configuration file is in the root directory, which can be adjusted as required
        config.AddJsonFile("autofac.json");
        // Register the ConfigurationModule with Autofac. 
        IConfigurationRoot configBuild = config.Build();
        // Read the configuration file to configure the service to register
        var module = new ConfigurationModule(configBuild);
        containerBuilder.RegisterModule(module);
        #endregion}}Copy the code

Autofec. json is placed in the root directory as follows:

//singleinstance, perlifetimescope, perdependency, perrequest
{
    "defaultAssembly": "Microsoft.EntityFrameworkCore".// The name of the assembly where the abstraction resides
    "components": [{"type": "Shop.EF.Model.shopdbContext,Shop.EF.Model".// The full implementation class name of the interface
        "services": [{"type": "Microsoft.EntityFrameworkCore.DbContext" // Full name of the interface}]."instanceScope": "single-instance"."injectProperties": true
      },
      {
        "type": "Shop.Service.BaseService,Shop.Service".// The full implementation class name of the interface
        "services": [{"type": "Shop.Interface.IBaseService,Shop.Interface" // Full name of the interface}]."instanceScope": "single-instance"."injectProperties": true
      },
      {
        "type": "Shop.Service.UserService,Shop.Service".// The full implementation class name of the interface
        "services": [{"type": "Shop.Interface.IUserService,Shop.Interface" // Full name of the interface}]."instanceScope": "single-instance"."injectProperties": true
      },
      {
        "type": "Shop.Service.ProductService,Shop.Service".// The full implementation class name of the interface
        "services": [{"type": "Shop.Interface.IProductService,Shop.Interface" // Full name of the interface}]."instanceScope": "single-instance"."injectProperties": true
      },
      {
        "type": "Shop.Service.OrderService,Shop.Service".// The full implementation class name of the interface
        "services": [{"type": "Shop.Interface.IOrderService,Shop.Interface" // Full name of the interface}]."instanceScope": "single-instance"."injectProperties": true}}]Copy the code