当前位置:网站首页>Autofac details
Autofac details
2022-06-23 23:31:00 【Brother Li Yu】
Autofac Detailed explanation
zero 、 List of articles
One 、Autofac Detailed explanation
1、 summary
- Autofac Is the third party IOC Containers , It's the most popular IOC Containers .
- Powerful , Than asp.netcore Built in containers are much more powerful , Support attribute injection and method injection , Support AOP.
- Official website address :http://autofac.org/
- Source code download address :https://github.com/autofac/Autofac
2、 Quick start
(1)Nuget Bring in the package
Autofac Based on version 6.3 demonstration ,Net5
(2) Container creation object
// Create a container builder
ContainerBuilder containerBuilder = new ContainerBuilder();
// Registered general class
containerBuilder.RegisterType<Honer>();
//build once , Get a container
IContainer container = containerBuilder.Build();
// You can get instances of objects based on containers
Honer phone = container.Resolve<Honer>();
3、 Type of registration
(1) Registered general class
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>();
IContainer container = containerBuilder.Build();
Honer phone = container.Resolve<Honer>();
(2) Registration abstraction and implementation
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
IContainer container = containerBuilder.Build();
IPhone phone = container.Resolve<IPhone>();
(3) Register assembly
- RegisterAssemblyTypes( Assembly array ), Assembly must be public Of
- AsImplementedInterfaces(): Indicates the type of registration , Register as an interface
- PropertiesAutowired(): Support attribute Injection
- Where: Meet the condition type registration
var basePath = AppContext.BaseDirectory;
var dll = Path.Combine(basePath, "MyAutofac.dll");
ContainerBuilder containerBuilder = new ContainerBuilder();
var assemblysServices = Assembly.LoadFrom(dll);
containerBuilder.RegisterAssemblyTypes(assemblysServices)
.Where(t => !t.Name.EndsWith("XXX"))
.AsImplementedInterfaces()
.PropertiesAutowired();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

4、 Three injection methods
(1) Constructor injection
The default support , Cannot filter with attributes , By default, the constructor with the most parameters is selected for injection
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>();
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

(2) All attribute injection
key word
PropertiesAutowired, All the attributes of this object are injected
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired();
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

(3) Attribute injection of tag features
key word
PropertiesAutowired, Define the property selectorCustomPropertySelector
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired(new CustomPropertySelector());
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();
public class CustomPropertySelector : IPropertySelector
{
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
var flag = propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(SelectPropAttribute));
return flag;
}
}

(4) Methods to inject
key word
OnActivated, Specifies the calling method
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>()
.OnActivated(p =>
{
p.Instance.SetStudent1(p.Context.Resolve<IStudent>());
});
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

5、 Object lifecycle
(1) Instantaneous life cycle
Each acquisition is a new instance , key word
InstancePerDependency, The default life cycle
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerDependency();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerDependency:phone1==phone2=>{isflg1}");
InstancePerDependency:phone1==phone2=>False
(2) Single instance life cycle
There is the same instance in the same process , key word
SingleInstance
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().SingleInstance();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"SingleInstance:phone1==phone2=>{isflg1}");
using (var scope = container.BeginLifetimeScope())
{
IPhone phone3 = scope.Resolve<IPhone>();
IPhone phone4 = scope.Resolve<IPhone>();
bool isflg2 = object.ReferenceEquals(phone3, phone4);
Console.WriteLine($"SingleInstance:phone3==phone4=>{isflg2}");
bool isflg3 = object.ReferenceEquals(phone1, phone3);
Console.WriteLine($"SingleInstance:phone1==phone3=>{isflg3}");
}
SingleInstance:phone1==phone2=>True
SingleInstance:phone3==phone4=>True
SingleInstance:phone1==phone3=>True
(3) Scope lifecycle
There is the same instance in the same scope , key word
InstancePerLifetimeScope
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerLifetimeScope();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerLifetimeScope:phone1==phone2=>{isflg1}");
IPhone phone3 = null;
IPhone phone4 = null;
using (var scope = container.BeginLifetimeScope())
{
phone3 = scope.Resolve<IPhone>();
phone4 = scope.Resolve<IPhone>();
bool isflg2 = object.ReferenceEquals(phone3, phone4);
Console.WriteLine($"InstancePerLifetimeScope:phone3==phone4=>{isflg2}");
bool isflg3 = object.ReferenceEquals(phone1, phone3);
Console.WriteLine($"InstancePerLifetimeScope:phone1==phone3=>{isflg3}");
}
IPhone phone5 = null;
IPhone phone6 = null;
using (var scope = container.BeginLifetimeScope())
{
phone5 = scope.Resolve<IPhone>();
phone6 = scope.Resolve<IPhone>();
bool isflg2 = object.ReferenceEquals(phone5, phone6);
Console.WriteLine($"InstancePerLifetimeScope:phone5==phone6=>{isflg2}");
bool isflg3 = object.ReferenceEquals(phone1, phone5);
Console.WriteLine($"InstancePerLifetimeScope:phone1==phone5=>{isflg3}");
}
bool isflg4 = object.ReferenceEquals(phone3, phone5);
Console.WriteLine($"InstancePerLifetimeScope:phone3==phone5=>{isflg4}");
InstancePerLifetimeScope:phone1==phone2=>True
InstancePerLifetimeScope:phone3==phone4=>True
InstancePerLifetimeScope:phone1==phone3=>False
InstancePerLifetimeScope:phone5==phone6=>True
InstancePerLifetimeScope:phone1==phone5=>False
InstancePerLifetimeScope:phone3==phone5=>False
(4) Scope scope lifecycle
Cannot create instance outside scope , Within the scope , Objects under the same scope are the same , key word
InstancePerMatchingLifetimeScope
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerMatchingLifetimeScope("scope1", "scope2");
IContainer container = containerBuilder.Build();
IPhone phone1 = null;
IPhone phone2 = null;
using (var scope = container.BeginLifetimeScope("scope1"))
{
phone1 = scope.Resolve<IPhone>();
phone2 = scope.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone2=>{isflg1}");
}
IPhone phone3 = null;
using (var scope = container.BeginLifetimeScope("scope2"))
{
phone3 = scope.Resolve<IPhone>();
}
IPhone phone4 = null;
using (var scope = container.BeginLifetimeScope("scope2"))
{
phone4 = scope.Resolve<IPhone>();
}
bool isflg2 = object.ReferenceEquals(phone3, phone4);
Console.WriteLine($"InstancePerMatchingLifetimeScope:phone3==phone4=>{isflg2}");
bool isflg3 = object.ReferenceEquals(phone1, phone3);
Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone3=>{isflg3}");
InstancePerMatchingLifetimeScope:phone1==phone2=>True
InstancePerMatchingLifetimeScope:phone3==phone4=>False
InstancePerMatchingLifetimeScope:phone1==phone3=>False
(5) Request the same object at a time
key word
InstancePerRequest, Only in web Debugging in project , Console error
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerRequest();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerRequest:phone1==phone2=>{isflg1}");
6、 Support profile registration
(1)nuget Import assembly
Autofac
Autofac.Configuration
Microsoft.Extensions.Configuration.Json
(2) The configuration file autofac.json, attribute -> Always copy
{
"components": [
{
// Realization
"type": "Net5.IOC.Honer,Net5.IOC",
// abstract
"services": [
{
"type": "Net5.IOC.IPhone,Net5.IOC"
}
],
// Life cycle
"instanceScope": "single-instance",
// Attribute injection
"injectProperties": true
}
]
}
(3) Create objects through configuration file registration
ContainerBuilder containerBuilder = new ContainerBuilder();
IConfigurationBuilder config = new ConfigurationBuilder();
IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource()
{
Path = "Autofac/autofac.json",
Optional = false,//boolean, The default is false, Don't write
ReloadOnChange = true,// ditto
};
config.Add(autofacJsonConfigSource);
ConfigurationModule module = new ConfigurationModule(config.Build());
containerBuilder.RegisterModule(module);
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($" Profile registration :phone1==phone2=>{isflg1}");
(4) Running results
Profile registration :phone1==phone2=>True
7、 Support AOP Faceted programming
You can... Without modifying the method , Add common logic before and after methods , journal , abnormal , Cache, etc
(1)nuget Import assembly
Castle.Core
Autofac.Extras.DynamicProxy
(2) Customize an aspect class implementation IInterceptor Interface
public class CustomInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine(" Before method execution ...");
// Execute the current method
invocation.Proceed();
Console.WriteLine(" After method execution ...");
}
}
(3) In the abstract / Add attribute tags to the implementation class
[Intercept(typeof(CustomInterceptor))]
public interface IPhone
{
string ShowName();
}
// Implement class virtual methods
public class Honer : IPhone
{
public virtual string ShowName()
{
Console.WriteLine("Honer");
return "Honer";
}
}
(4) Register the relationship creation object in the container
- EnableInterfaceInterceptors + Feature tags are abstract , All implementation classes support AOP
- EnableInterfaceInterceptors + Attributes are marked on the implementation class , Tagged classes support AOP
- EnableClassInterceptors, To support AOP The method must be used virtual Virtual method
- EnableClassInterceptors + Feature tags are abstract , All implementation classes support AOP
- EnableClassInterceptors + Attributes are marked on the implementation class , Tagged classes support AOP
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().EnableInterfaceInterceptors();
containerBuilder.RegisterType(typeof(CustomInterceptor));
IContainer container = containerBuilder.Build();
IPhone phone = container.Resolve<IPhone>();
phone.ShowName();
(5) Running results
Before method execution ...
Honer
After method execution ...
8、 Single abstract multiple implementation problem
(1) Register the relationship creation object in the container
Do not mark your name when registering , Those registered later will overwrite those registered earlier
Mark your name when you register , When creating objects, use names to distinguish
ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().Named<IPhone>("Honer");
containerBuilder.RegisterType<Huawei>().Named<IPhone>("Huawei");
IContainer container = containerBuilder.Build();
IPhone honer = container.ResolveNamed<IPhone>("Honer");
IPhone huawei = container.ResolveNamed<IPhone>("Huawei");
honer.ShowName();
huawei.ShowName();
(2) Running results
Honer
Huawei
9、 Integrated into the Asp.NetCore5 frame
(1)nuget Import assembly
Autofac
Autofac.Extensions.DependencyInjection
(2) Define implementation classes and abstractions
public class UserService : IUserService
{
private IUserRepository UserRepositoryCtor { get; set; }
public UserService(IUserRepository userRepository)
{
UserRepositoryCtor = userRepository;
}
public string Login(string username, string password)
{
return " Login successful ";
}
}
(3) Add controllers and pages
public class FourthController : Controller
{
private IUserService _userService;
public FourthController(IUserService userService)
{
this._userService = userService;
}
public IActionResult Index()
{
object result = this._userService.Login("username", "password");
return View(result);
}
}
@model String
<h2>this is fourth index...</h2>
<h2>@Model</h2>
(4) stay Program Replace container factory
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
}
(5) stay Startup Class ConfigureServices Method to replace the class that creates the controller
// By default, the controller has IControllerActivator Created , Replace with created by the container
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
(6) Register the relationship between abstraction and implementation
stay
StartupAdd a method to the classConfigureContainer, Used to register abstractions and implement , These registration information can be modularized and encapsulated intoAutofacModuleWhen there are many abstract classes and implementations , You can put the whole dll register , The special relationship can be written later to cover the previous registration relationship .
/// <summary>
/// Autofac special : Register the relationship between abstraction and detail , Use autofac The original built-in registration relationship should be commented out
/// Autofac and ServiceCollection It is the coexistence of the two ,Autofac Will take over ServiceCollection Everything
/// </summary>
/// <param name="builder"></param>
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule<AutofacModule>();
}
public class AutofacModule : Module
{
/// <summary>
/// rewrite Autofac In the pipe Load Method , Inject registered content here
/// </summary>
/// <param name="builder"></param>
protected override void Load(ContainerBuilder builder)
{
// Registration abstraction and implementation
builder.RegisterType<UserRepository>().As<IUserRepository>();
builder.RegisterType<UserService>().As<IUserService>();
// Register all controller classes
var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
.Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
// Implement attribute Injection , Method injection cannot be implemented here
builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
}
}
(7) Running results


(8) stay Startup Of Configure Method to create objects with containers
using (var container = host.Services.CreateScope())
{
IUserService userService = container.ServiceProvider.GetService<IUserService>();
}

(9) Single abstract multi implementation integration into framework
When injecting, inject through constructor or attribute autofac Context instance , Then create the corresponding instance according to the name .
Define single abstract and multi instance classes
// abstract
public interface ITestService
{
string Show();
}
// Realization 1
public class TestServiceA : ITestService
{
public string Show()
{
return "TestServiceA";
}
}
// Realization 2
public class TestServiceB : ITestService
{
public string Show()
{
return "TestServiceB";
}
}
stay
AutofacModuleRegister the relationship between abstraction and implementation
// Single abstract multi implementation registration
builder.RegisterType<TestServiceA>().Named<ITestService>("a");
builder.RegisterType<TestServiceB>().Named<ITestService>("b");
Add controllers and pages
public class FifthController : Controller
{
private IComponentContext _componentContext;
public FifthController(IComponentContext componentContext)
{
this._componentContext = componentContext;
}
public IActionResult Index()
{
ITestService testServiceA = _componentContext.ResolveNamed<ITestService>("a");
ITestService testServiceB = _componentContext.ResolveNamed<ITestService>("b");
object result = $"{testServiceA.Show()}--{testServiceB.Show()}";
return View(result);
}
}
@model String
<h2>this is Fifth index...</h2>
<h2>@Model</h2>
Running results

边栏推荐
- 项目中常用到的 19 条 MySQL 优化
- Giants end up "setting up stalls" and big stalls fall into "bitter battle"
- 国家邮政局等三部门:加强涉邮政快递个人信息安全治理,推行隐私面单、虚拟号码等个人信息去标识化技术
- CTF—Go题目复现
- Troubleshooting of undefined problems in the channel list of easynvr channel management
- 数据解读!理想L9冲刺「月销过万」,从BBA手中抢份额
- How does the fortress connection key server associate with the server host?
- "Shanda Diwei Cup" the 12th Shandong ICPC undergraduate program design competition
- [design] 1359- how umi3 implements plug-in architecture
- The sandbox week is coming!
猜你喜欢

【HackTheBox】 meow

ASM文件系统 数据如何写和读数据
Detailed usage of exists in SQL statements

The sandbox and bayz have reached cooperation to jointly drive the development of metauniverse in Brazil

C WinForm custom progress bar ProgressBar
Summary of cloud native pipeline tools

How can wechat video numbers be broadcast live on a PC?
Androidkotlin comprehensive and detailed class usage grammar learning guide

The 12 SQL optimization schemes summarized by professional "brick moving" old drivers are very practical!

百万消息量IM系统技术要点分享
随机推荐
什么是免疫组织化学实验? 免疫组织化学实验
【观察】戴尔科技+英特尔傲腾技术:以“纳秒之速”领跑存储创新
短视频挺进在线音乐腹地
巨头下场“摆摊”,大排档陷入“苦战”
AIX系统月维护查什么(二)
C# 读取内存条占用大小,硬盘占用大小
PHP timestamp
How PostgreSQL creates partition tables
3D打印和激光切割流程的初步了解
项目中常用到的 19 条 MySQL 优化
生鲜前置仓的面子和里子
AIX system monthly maintenance check (I)
[Xilinx ax7103 microbalze Learning Notes 6] MicroBlaze custom IP core packaging experiment
Desai wisdom number - histogram (basic histogram): the way to celebrate father's day in 2022
Urgent! Tencent cloud container security supports the detection of Apache log4j2 vulnerabilities for the first time. It is in free trial
Some explanations of Tim timer of embedded interface and STM32 template library function of NVIC
AIX系统月维护查什么(一)
The latest February activity # 1 core 2G first year: 38 yuan / year! 2-core 4G light weight RMB 74 / year! Mysql database 19.9 yuan / year!!
Oracle turn off recycle bin
The Sandbox 与 BAYZ 达成合作,共同带动巴西的元宇宙发展