See .NET Core source dependency achieved by injection into the Controller attribute Autofac

I. Introduction

  In the previous article [ASP.NET Core integration Autofac and Castle automatic AOP interception] , we talked about addition to ASP.NETCore own IOC container, how to use Autofac to take over the IServiceProvider dependency injection.

  Recently, the old idea of ​​dependency injection property value in ASP.NET Mvc Core Controller, but it searched Microsoft.Extensions.DependencyInjection library did not find a corresponding method, and is found for the constructor after viewing the source code dependency injection, and no attribute or field dependency injection.

  Official gives us two ways of getting results dependency injection method: ActivatorUtilities.CreateInstance and IServiceProvider.GetService , the difference between these two methods, I will not elaborate, and friends who are interested can go look through the two classes source: ServiceProvider and ActivatorUtilities , but generally speaking, two methods are not injected attribute values when creating objects.

  Simple call two methods: First, Startup.ConfigureServices function, add statements services.AddTransient <IUser, MyUser> ();

  1. IUser user = ActivatorUtilities.CreateInstance(serviceProvider, typeof(IUser));
  2. IUser user = serviceProvider.GetService(typeof(IUser))

  These two functions return the results are the same, and if there is the interface type MyUser the constructor, then the two methods will also perform dependency injection, but will not create object attributes injection. But these two methods there are differences of principle, ActivatorUtilities is constructed by means of building ExpressionTree type constructor and create an object and use the IServiceProvider injected constructor; and ServiceProvider is completely dependent on injected through life CallSite cycle, to create objects of type recursive.

  If I have to say that the method is better, then there is an obvious IServiceProvider interface, ActivatorUtilities is a set of methods, and ASP.NET Core of DI life cycle everywhere ServiceProvider figure, its ability to expand without having to explain.

Second, the use Autofac

  Which makes this example is to use Autofac just lazy, mainly autofac support dependency properties have been injected. But does not directly use, by studying ASP.NET Core MVC source code, I found a solution, and with the Autofac to complete dependence Controller property of injecting operation.

  We describe a Autofac mentioned in the article, by modifying Autofac Startup.ConfigureServices function return value, and returns the value to be modified by the void IServiceProvider accomplished.

Copy the code
public IServiceProvider ConfigureServices(IServiceCollection services)
{
     var builder = new ContainerBuilder();
     services.AddMvc();
     builder.Populate(services);
     this.ApplicationContainer = builder.Build();
     return new AutofacServiceProvider(this.ApplicationContainer);
}
Copy the code

  By returning AutofacServiceProvider type IServiceProvider, Autofac decorative pattern on the adoption took over ServiceProvider. But only after taking over IServiceProvider, we will find that this does not inject property value, through the study of ASP.NET Core source code, compiled the following ideas:

  1. Locate the Controller of all types

var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new AssemblyPart(assembly));
manager.FeatureProviders.Add(new ControllerFeatureProvider());
var feature = new ControllerFeature();
manager.PopulateFeature(feature);

   By ApplicationPartManager, ASP.NET Core manages all program components, AssemblyPart here is an assembly component, that will focus on ASP.NET Core MVC Controller type or look for other types used in this procedure. We can also be added by this method a program set for the MVC project is split into two separate projects, such as Project Controller and View projects.

  This class ControllerFeatureProvider see the name to know that it is used to find the Controller type. Let's pick it for a look at the code:

Copy the code
public void PopulateFeature(IEnumerable<ApplicationPart> parts,ControllerFeature feature)
{
     foreach (var part in parts.OfType<IApplicationPartTypeProvider>())
     {
          foreach (var type in part.Types)
          {
              if (IsController(type) &&!feature.Controllers.Contains(type))
              {
                  feature.Controllers.Add(type);
              }
          }
      }
}
Copy the code

  2. to register the Controller type by Autofac

 builder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired();

 

  Autofac ControllerFeature by the Controller of the IOC for registration, and using turn PropertiesAutowired injection property.

 

  3. Modify the default Controller creator, Autofac use of ServiceProvider complete the creation of the work of the Controller.

  This is the most important step, by viewing the source code for ASP.NET Core Controller for use DefaultControllerActivator class work created by default; but finding the Create function of this class is to release it in fact calls ActivatorUtilities to create the object. Have said before in this case, when you create an object of type, IServiceProvdier only responsible for the constructor parameters to find the injection, that create objects or to create a ActivatorUtilities out, so it is useless to replace the use of the autofac ServiceProvider, That ActivatorUtilities does not extend to the point of use we provide to be replaced, so that has caused the problem can not be injected.

  The following code is added to Services.AddMvc (); prior to, the following:

 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

 

  In fact, with ServiceBasedControllerActivator to replace the default DefaultControllerActivator; look at its source code for it, you will understand:

Copy the code
 public object Create(ControllerContext actionContext)
 {
      if (actionContext == null)
      {
          throw new ArgumentNullException(nameof(actionContext));
      }

      var controllerType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType();
      return actionContext.HttpContext.RequestServices.GetRequiredService(controllerType);
}
Copy the code

 

  RequestServices here is IServiceProvider so know everything, and here we are already used to replace the over-use Provider.

  Finally, add a Demo, look at the properties User is not being injected into the value of:

Copy the code
 public class HomeController : Controller
{
        public IUserManager User { set; get; }

        public IActionResult Index()
        {
            User.Register("hello");
            return View();
        }
}
Copy the code

 

 

Third, and finally

  ASP.NET Core source code is really a good learning materials, every component is an extension, each component has a set of widgets; the real component development!  

  

  DEMO's Git address: https://github.com/maxzhang1985/AutofacCastle.AspNetCore.Demo

 

  GitHub: https://github.com/maxzhang1985/YOYOFx   if sleep also can ask Star , the welcome exchange.

 

  .NET Core and YOYOFx exchange group:  214 741 894  

  

 
 
12
0
 
 
 
<<  Previous:  elaborate ASP.NET Core static file caching mode
>>  Next:  ASP.NET Core in ActionFilter and DI

I. Introduction

  In the previous article [ASP.NET Core integration Autofac and Castle automatic AOP interception] , we talked about addition to ASP.NETCore own IOC container, how to use Autofac to take over the IServiceProvider dependency injection.

  Recently, the old idea of ​​dependency injection property value in ASP.NET Mvc Core Controller, but it searched Microsoft.Extensions.DependencyInjection library did not find a corresponding method, and is found for the constructor after viewing the source code dependency injection, and no attribute or field dependency injection.

  Official gives us two ways of getting results dependency injection method: ActivatorUtilities.CreateInstance and IServiceProvider.GetService , the difference between these two methods, I will not elaborate, and friends who are interested can go look through the two classes source: ServiceProvider and ActivatorUtilities , but generally speaking, two methods are not injected attribute values when creating objects.

  Simple call two methods: First, Startup.ConfigureServices function, add statements services.AddTransient <IUser, MyUser> ();

  1. IUser user = ActivatorUtilities.CreateInstance(serviceProvider, typeof(IUser));
  2. IUser user = serviceProvider.GetService(typeof(IUser))

  These two functions return the results are the same, and if there is the interface type MyUser the constructor, then the two methods will also perform dependency injection, but will not create object attributes injection. But these two methods there are differences of principle, ActivatorUtilities is constructed by means of building ExpressionTree type constructor and create an object and use the IServiceProvider injected constructor; and ServiceProvider is completely dependent on injected through life CallSite cycle, to create objects of type recursive.

  If I have to say that the method is better, then there is an obvious IServiceProvider interface, ActivatorUtilities is a set of methods, and ASP.NET Core of DI life cycle everywhere ServiceProvider figure, its ability to expand without having to explain.

Second, the use Autofac

  Which makes this example is to use Autofac just lazy, mainly autofac support dependency properties have been injected. But does not directly use, by studying ASP.NET Core MVC source code, I found a solution, and with the Autofac to complete dependence Controller property of injecting operation.

  We describe a Autofac mentioned in the article, by modifying Autofac Startup.ConfigureServices function return value, and returns the value to be modified by the void IServiceProvider accomplished.

Copy the code
public IServiceProvider ConfigureServices(IServiceCollection services)
{
     var builder = new ContainerBuilder();
     services.AddMvc();
     builder.Populate(services);
     this.ApplicationContainer = builder.Build();
     return new AutofacServiceProvider(this.ApplicationContainer);
}
Copy the code

  By returning AutofacServiceProvider type IServiceProvider, Autofac decorative pattern on the adoption took over ServiceProvider. But only after taking over IServiceProvider, we will find that this does not inject property value, through the study of ASP.NET Core source code, compiled the following ideas:

  1. Locate the Controller of all types

var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new AssemblyPart(assembly));
manager.FeatureProviders.Add(new ControllerFeatureProvider());
var feature = new ControllerFeature();
manager.PopulateFeature(feature);

   By ApplicationPartManager, ASP.NET Core manages all program components, AssemblyPart here is an assembly component, that will focus on ASP.NET Core MVC Controller type or look for other types used in this procedure. We can also be added by this method a program set for the MVC project is split into two separate projects, such as Project Controller and View projects.

  This class ControllerFeatureProvider see the name to know that it is used to find the Controller type. Let's pick it for a look at the code:

Copy the code
public void PopulateFeature(IEnumerable<ApplicationPart> parts,ControllerFeature feature)
{
     foreach (var part in parts.OfType<IApplicationPartTypeProvider>())
     {
          foreach (var type in part.Types)
          {
              if (IsController(type) &&!feature.Controllers.Contains(type))
              {
                  feature.Controllers.Add(type);
              }
          }
      }
}
Copy the code

  2. to register the Controller type by Autofac

 builder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired();

 

  Autofac ControllerFeature by the Controller of the IOC for registration, and using turn PropertiesAutowired injection property.

 

  3. Modify the default Controller creator, Autofac use of ServiceProvider complete the creation of the work of the Controller.

  This is the most important step, by viewing the source code for ASP.NET Core Controller for use DefaultControllerActivator class work created by default; but finding the Create function of this class is to release it in fact calls ActivatorUtilities to create the object. Have said before in this case, when you create an object of type, IServiceProvdier only responsible for the constructor parameters to find the injection, that create objects or to create a ActivatorUtilities out, so it is useless to replace the use of the autofac ServiceProvider, That ActivatorUtilities does not extend to the point of use we provide to be replaced, so that has caused the problem can not be injected.

  The following code is added to Services.AddMvc (); prior to, the following:

 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

 

  In fact, with ServiceBasedControllerActivator to replace the default DefaultControllerActivator; look at its source code for it, you will understand:

Copy the code
 public object Create(ControllerContext actionContext)
 {
      if (actionContext == null)
      {
          throw new ArgumentNullException(nameof(actionContext));
      }

      var controllerType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType();
      return actionContext.HttpContext.RequestServices.GetRequiredService(controllerType);
}
Copy the code

 

  RequestServices here is IServiceProvider so know everything, and here we are already used to replace the over-use Provider.

  Finally, add a Demo, look at the properties User is not being injected into the value of:

Copy the code
 public class HomeController : Controller
{
        public IUserManager User { set; get; }

        public IActionResult Index()
        {
            User.Register("hello");
            return View();
        }
}
Copy the code

 

 

Third, and finally

  ASP.NET Core source code is really a good learning materials, every component is an extension, each component has a set of widgets; the real component development!  

  

  DEMO's Git address: https://github.com/maxzhang1985/AutofacCastle.AspNetCore.Demo

 

  GitHub: https://github.com/maxzhang1985/YOYOFx   if sleep also can ask Star , the welcome exchange.

 

  .NET Core and YOYOFx exchange group:  214 741 894  

  

Guess you like

Origin www.cnblogs.com/webenh/p/11605619.html