Use of AutoFac of Net Core
- 2021-11-29 23:41:00
- OfStack
This article does not introduce the concepts of IoC and DI. If you don't know Ioc before, it is recommended to search for relevant information under 1 first
This article will briefly introduce the basic use of AutoFac under 1 and its application in asp. net core
Introduction to Autofac
Three ways to register components
1. Reflex
2. Ready-made examples (new)
3. lambda expression (1 anonymous method that executes an instantiated object)
Here are a few short examples. I will list as many common registration methods as possible, and explain the meanings of the terms "component" and "service" in the comments
// Object for a registered component builder
var builder = new ContainerBuilder();
// Register components by type ConsoleLogger Leak service: ILogger
builder.RegisterType<ConsoleLogger>().As<ILogger>();
// Register components by type ConsoleLogger, Expose all services (interfaces) it implements
builder.RegisterType<ConsoleLogger>().AsImplementedInterfaces();
// Register components according to instances output Leak service: TextWriter
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
// Expression registers the component, where we pass parameters when constructing the function ->"musection" Leak service: IConfigReader
builder.Register(c =new ConfigReader("mysection")).As<IConfigReader>();
// Expression registration component , Analytic time transmission parameter
var service = scope.Resolve<IConfigReader>(
new NamedParameter("section", "mysection"));
// Reflection registration component, which directly registers ConsoleLogger Class (must be a concrete class), if ConsoleLogger There are multiple constructors, and the constructor with the most parameters will be instantiated
builder.RegisterType<ConsoleLogger>();
// Reflection registration component, manually specify the constructor, which specifies the call MyComponent ( ILogger log,IConfigReader config ) to register the constructor of
builder.RegisterType<MyComponent>()
.UsingConstructor(typeof(ILogger), typeof(IConfigReader));
// Registration MySingleton Static variables in the class "Instance" , ExternallyOwned() Function specifies the life cycle of its own control instance, instead of being defined by the autofac Automatic release
builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();
//1 Two services are exposed by two components
builder.RegisterType<CallLogger>().As<ILogger>().As<ICallInterceptor>();
// Registers the current assembly with the Service "Ending class
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces();
// Registration "MyApp.Repository" All classes in the assembly
builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
// Build 1 Containers complete registration
var rootcontainer = builder.Build();
// You can get it manually in the following way IConfigReader Implementation class of
// This manual parsing method requires Getting Components from Lifecycle Scope , To ensure that the component is finally released
// Do not go directly from the root container rootcontainer Parsing components in, it is very likely that memory leaks will be caused
using(var scope = rootcontainer.BeginLifetimeScope())
{
var reader = scope.Resolve<IConfigReader>();
}
If more than one component exposes the same service, Autofac uses the last registered component as the service provider. To override this behavior, use the
PreserveExistingDefaults()
Method modification
Life cycle
using(var scope = rootcontainer.BeginLifetimeScope())
The above code creates a life cycle scope
The lifecycle scope is releasable, and component 1 resolved within the scope must be guaranteed to use within using or finally manually call the component's Dispose () function
Avoid the life cycle of the referenced class being longer than the life cycle of the referenced class: if service references repository, if the life cycle of service is a singleton, the life cycle of repository is perrequest. service will not be released, so eventually the associated repository will never be released (Captive Dependencies)
Although we need to avoid parsing components directly from the root container as much as possible, there are always exceptions. For non-singleton components, 1 don't forget to call the Dispose function of the component. In fact, for non-singleton components, from the project architecture, in theory, it should be injected from the constructor instead of manually parsing. What needs to be parsed manually should be 1 configuration help class, etc.
The life cycle of a specific component (class) is divided into the following types (the latter functions are the functions corresponding to autofac):
Dependent on 1 instance each (Instance Per Dependency) (default)--InstancePerDependency () Single 1 instance (Single Instance) Single case--SingleInstance () 1 instance per lifecycle scope (Instance Per Lifetime Scope)--InstancePerLifetimeScope () 1 instance per matched lifecycle scope (Instance Per Matching Lifetime Scope)--InstancePerMatchingLifetimeScope () 1 instance per request (Instance Per Request) asp. net web Request--InstancePerRequest () Have 1 instance at a time (Instance Per Owned)--InstancePerOwned ()
If you have used autofac in the traditional ASP. NET MVC project before, there are one differences to note:
. required in net CoreInstancePerLifetimeScope
Replace the previous (traditional asp. net)InstancePerRequest
Ensuring that only 1 dependent instance is created per HTTP request.InstancePerRequest
The request level no longer exists The registration mode of Web, Api and Mvc in net, Core Registered controllers are no longer required in. net Core. The controllers are created by. net core and are not managed by autofac (except for the controller constructor), which explains why they are no longer usedInstancePerRequest
Life cycle, but it can be passed throughAddControllersAsServices()
Function changes, you can see: https://www.strathweb.com/2016/03/the-subtle-perils-of-controller-dependency-injection-in-asp-net-core-core-mvc/
Application of AutoFac in asp. net core
Using autofac in. net core is still relatively simple. Compared with the traditional asp. net web project, many steps are omitted
Introducing the nuget package:
Autofac Autofac.Extensions.DependencyInjectionCode in startup:
public static IContainer AutofacContainer;
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Registration service entry IServiceCollection
services.AddMvc();
ContainerBuilder builder = new ContainerBuilder();
// Will services To populate the service in the Autofac Medium .
builder.Populate(services);
// New module component registration
builder.RegisterModule<DefaultModuleRegister>();
// Create a container .
AutofacContainer = builder.Build();
// Using containers to create AutofacServiceProvider
return new AutofacServiceProvider(AutofacContainer);
}
The above code calls builder's
RegisterModule
Function, which requires passing in 1TModule
A module called autofacThe function of the module is to put all the relevant registration configurations in one class, which makes the code easier to maintain and configure, as shown below
DefaultModuleRegister
Code in
DefaultModuleRegister:
public class DefaultModuleRegister : Module
{
protected override void Load(ContainerBuilder builder)
{
// Registers the current assembly with the Ser "Ending class , All interfaces implemented by the burst class, with a life cycle of PerLifetimeScope
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Ser")).AsImplementedInterfaces().InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Repository")).AsImplementedInterfaces().InstancePerLifetimeScope();
// Register all "MyApp.Repository" Classes in an assembly
//builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
}
public static Assembly GetAssembly(string assemblyName)
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(AppContext.BaseDirectory + $"{assemblyName}.dll");
return assembly;
}
}
The release function of Autofac when the program stops can be selectively added to the Configure function:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// The program stops calling the function
appLifetime.ApplicationStopped.Register(() => { AutofacContainer.Dispose(); });
}
Code in Controller:
private IUserSer _user;
private IUserSer _user2;
public HomeController(IUserSer user, IUserSer user2)
{
_user = user;
_user2 = user2;
}
public IActionResult Index()
{
using (var scope = Startup.AutofacContainer.BeginLifetimeScope())
{
IConfiguration config = scope.Resolve<IConfiguration>();
IHostingEnvironment env = scope.Resolve<IHostingEnvironment>();
}
string name = _user.GetName();
string name2 = _user2.GetName();
return View();
}
As you can see, since we populated the services in IServiceCollection into autofac, we can now parse the services from AutoFac anywhere. The default injected services from net core (IConfiguration, IHostingEnvironment, etc.)
In normal project use, we should put
using(var scope = rootcontainer.BeginLifetimeScope())
0 Put it in a common class library so that all projects can call