您好,登錄后才能下訂單哦!
今天小編給大家分享一下.NET Core中怎么使用Autofac的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
Autofac 是一款.NET IoC 容器 . 它管理類之間的依賴關系, 從而使 應用在規模及復雜性增長的情況下依然可以輕易地修改 . 它的實現方式是將常規的.net類當做組件
處理.
安裝 NuGet 程序包: Autofac 6.0.0
創建一個 ContainerBuiler
注冊接口和實現關系
通過 ContainerBuiler 的 Build 方法,得到 IContainer 容器
通過 IContainer 容器獲取實例
使用服務
ITestServiceA
和 TestServiceA
public interface ITestServiceA { void Show(); } public class TestServiceA : ITestServiceA { public TestServiceA() { Console.WriteLine($"{this.GetType().Name} 被構造了..."); } public void Show() { Console.WriteLine($"This is a {this.GetType().Name} Instance..."); } }
Program 中的 Main
方法
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); var container = builder.Build(); // 獲取服務實例 var testService = container.Resolve<ITestServiceA>(); testService.Show();
ITestServiceB
和 TestServiceB
public interface ITestServiceB { void Show(); } public class TestServiceB : ITestServiceB { private ITestServiceA _testServiceA; public void SetService(ITestServiceA testServiceA) { _testServiceA = testServiceA; } public TestServiceB() { Console.WriteLine($"{this.GetType().Name} 被構造了..."); } public void Show() { // _testServiceA.Show(); Console.WriteLine($"This is a {this.GetType().Name} Instance..."); } }
ITestServiceC
和 TestServiceC
public interface ITestServiceC { void Show(); } public class TestServiceC : ITestServiceC { public TestServiceC() { Console.WriteLine($"{this.GetType().Name} 被構造了..."); } public void Show() { Console.WriteLine($"This is a {this.GetType().Name} Instance..."); } }
ITestServiceD
和 TestServiceD
public interface ITestServiceD { void Show(); } public class TestServiceD : ITestServiceD { public ITestServiceA TestServiceA { get; set; } public ITestServiceB TestServiceB { get; set; } public ITestServiceC TestServiceC { get; set; } public TestServiceD() { Console.WriteLine($"{this.GetType().Name} 被構造了..."); } public void Show() { // TestServiceA.Show(); // TestServiceB.Show(); // TestServiceC.Show(); Console.WriteLine($"This is a {this.GetType().Name} Instance..."); } }
構造函數注入
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceB>().As<ITestServiceB>(); builder.RegisterType<TestServiceC>().As<ITestServiceC>(); builder.RegisterType<TestServiceD>().As<ITestServiceD>(); var container = builder.Build(); // 獲取服務實例 var testService = container.Resolve<ITestServiceA>(); testService.Show();
屬性注入
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceB>().As<ITestServiceB>(); builder.RegisterType<TestServiceC>().As<ITestServiceC>(); builder.RegisterType<TestServiceD>().As<ITestServiceD>().PropertiesAutowired(); var container = builder.Build(); // 獲取服務實例 var testService = container.Resolve<ITestServiceD>(); testService.Show();
方法注入
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceB>().OnActivated(e => e.Instance.SetService(e.Context.Resolve<ITestServiceA>()) ).As<ITestServiceB>(); builder.RegisterType<TestServiceC>().As<ITestServiceC>(); builder.RegisterType<TestServiceD>().As<ITestServiceD>(); var container = builder.Build(); // 獲取服務實例 var testService = container.Resolve<ITestServiceB>(); testService.Show();
InstancePerDependency :默認模式,每次調用,都會重新實例化對象;每次請求都創建一個新的對象;
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>().InstancePerDependency(); var container = builder.Build(); var testServiceA = container.Resolve<ITestServiceA>(); var testServiceA1 = container.Resolve<ITestServiceA>(); Console.WriteLine(object.ReferenceEquals(testServiceA,testServiceA1));
SingleInstance :單例模式,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>().SingleInstance(); var container = builder.Build(); var testServiceA = container.Resolve<ITestServiceA>(); var testServiceA1 = container.Resolve<ITestServiceA>(); Console.WriteLine(object.ReferenceEquals(testServiceA,testServiceA1));
InstancePerLifetimeScope : 同一個生命周期域中,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;且每個不同的生命周期域中的實例是唯一的,不共享的。
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>().InstancePerLifetimeScope(); var container = builder.Build(); ITestServiceA testServiceA15; ITestServiceA testServiceA16; using (var scope1 = container.BeginLifetimeScope()) { var testServiceA11 = scope1.Resolve<ITestServiceA>(); var testServiceA12 = scope1.Resolve<ITestServiceA>(); Console.WriteLine(object.ReferenceEquals(testServiceA11,testServiceA12)); testServiceA15 = testServiceA12; } using (var scope1 = container.BeginLifetimeScope()) { var testServiceA13 = scope1.Resolve<ITestServiceA>(); var testServiceA14 = scope1.Resolve<ITestServiceA>(); Console.WriteLine(object.ReferenceEquals(testServiceA13,testServiceA14)); testServiceA16 = testServiceA14; } Console.WriteLine(object.ReferenceEquals(testServiceA15,testServiceA16));
InstancePerMatchingLifetimeScope : 同一個匹配的生命周期域中,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;且每個不匹配的生命周期域中的實例是唯一的,不共享的。
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>() .InstancePerMatchingLifetimeScope("Run2948"); var container = builder.Build(); ITestServiceA testServiceA15; ITestServiceA testServiceA16; using (var scope1 = container.BeginLifetimeScope("Run2948")) { var testServiceA11 = scope1.Resolve<ITestServiceA>(); using (var scope2 = container.BeginLifetimeScope()) { var testServiceA12 = scope2.Resolve<ITestServiceA>(); Console.WriteLine(object.ReferenceEquals(testServiceA11,testServiceA12)); } testServiceA15 = testServiceA11; } using (var scope1 = container.BeginLifetimeScope("Run2948")) { var testServiceA13 = scope1.Resolve<ITestServiceA>(); using (var scope2 = container.BeginLifetimeScope()) { var testServiceA14 = scope2.Resolve<ITestServiceA>(); Console.WriteLine(object.ReferenceEquals(testServiceA13,testServiceA14)); } testServiceA16 = testServiceA13; } Console.WriteLine(object.ReferenceEquals(testServiceA15,testServiceA16));
InstancePerOwned : 在一個所擁有的實例創建的生命周期中,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;(較少使用)
InstancePerHttpRequest : 同一次Http請求上下文中,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;僅適用于 ASP.NET (CORE) MVC 或 WebForm 應用程序
安裝 NuGet 程序包: Autofac.Extensions.DependencyInjection 7.1.0
、Autofac.Configuration 6.0.0
新建配置文件(指定接口和實現的對應關系) autofac.json
:
{ "components":[ { "type: "One.Services.TestServiceA,One", "services": [ { "type": "One.Services.ITestServiceA,One" } ], "instanceScope": "single-instance", "injectProperties": true }, { "type: "One.Services.TestServiceB,One", "services": [ { "type": "One.Services.ITestServiceB,One" } ], "instanceScope": "single-instance", "injectProperties": true }, { "type: "One.Services.TestServiceC,One", "services": [ { "type": "One.Services.ITestServiceC,One" } ], "instanceScope": "single-instance", "injectProperties": true }, { "type: "One.Services.TestServiceD,One", "services": [ { "type": "One.Services.ITestServiceD,One" } ], "instanceScope": "single-instance", "injectProperties": true } ] }
讀取配置文件,完成服務對應關系的注冊
var builder = new ContainerBuilder(); var config = new ConfigurationBuilder(); var configSource = new JsonConfigurationSource() { Path = "Config/autofac.json", Optional = false, ReloadOnChange = true }; config.Add(configSource); var configModule = new ConfigurationModule(config.Build()); builder.RegisterModule(configModule); var container = builder.Build(); // 獲取服務實例 var testServiceA = container.Resolve<ITestServiceA>(); var testServiceD = container.Resolve<ITestServiceD>(); testServiceD.Show();
新建 ITestServiceA 的新版實現類 TestServiceUpdate
public class TestServiceUpdate : ITestServiceA { public TestServiceUpdate() { Console.WriteLine($"{this.GetType().Name} 被構造了..."); } public void Show() { Console.WriteLine($"This is a {this.GetType().Name} Instance..."); } }
通過修改配置文件 autofac.json
來實現快速實現 ITestServiceA 的實現的重新定義:
{ "components":[ { "type: "One.Services.TestServiceUpdate,One", "services": [ { "type": "One.Services.ITestServiceA,One" } ], "instanceScope": "single-instance", "injectProperties": true }, // ...
安裝 NuGet 程序包: Autofac.Extensions.DependencyInjection 7.1.0
Program文件中指定 Autofac 工廠替換默認工廠:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }).UseServiceProviderFactory(new AutofacServiceProviderFactory());
在 Startup 類中增加 ConfigureContainer 方法:
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<TestServiceA>().As<ITestServiceA>(); }
通過控制器構造函數注入,獲取實例
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private readonly ITestServiceA _serviceA; public ValuesController(ITestServiceA serviceA { _serviceA = serviceA; } [HttpGet] public IActionResult Get() { _serviceA.Show(); return Ok(); } }
使用 IServiceCollection 注冊的服務,將來也會交給 Autofac 管理
public void ConfigureServices(IServiceCollection services) { #region IServiceCollection 注冊的服務,將來也會交給 Autofac 處理 services.AddTransient<ITestServiceA, TestServiceA>(); services.AddTransient<ITestServiceB, TestServiceB>(); services.AddTransient<ITestServiceC, TestServiceC>(); #endregion } public void ConfigureContainer(ContainerBuilder builder) { // builder.RegisterType<TestServiceA>().As<ITestServiceA>(); // builder.RegisterType<TestServiceB>().As<ITestServiceB>(); // builder.RegisterType<TestServiceC>().As<ITestServiceC>(); builder.RegisterType<TestServiceD>().As<ITestServiceD>(); }
控制器本身是一個類,它的實例其實是有 IControllerActivator 來創建的。
指定控制器的實例由容器來創建
public void ConfigureServices(IServiceCollection services) { // ... #region 指定控制器的實例由容器來創建 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>()); #endregion }
注冊控制器的抽象和具體的關系
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<TestServiceA>().As<ITestServiceA>().PropertiesAutowired(); builder.RegisterType<TestServiceB>().As<ITestServiceB>(); #region 注冊所有控制器的關系及控制器實例化所需要的組件 var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes() .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray(); builder.RegisterTypes(controllersTypesInAssembly) .PropertiesAutowired(); #endregion }
在控制器內定義屬性
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { public ITestServiceA TestServiceA { get; set; } public ITestServiceB TestServiceB { get; set; } [HttpGet] public IActionResult Get() { TestServiceA.Show(); TestServiceB.Show(); return Ok(); } }
擴展:自己控制哪些屬性需要做依賴注入(默認是讓控制器中的屬性都依賴注入)
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public class AutowaredAttribute : Attribute { } public class PropertySelector : IPropertySelector { public bool InjectProperty(PropertyInfo propertyInfo, object instance) { return propertyInfo.CustomAttributes.Any(ca => ca.AttributeType == typeof(AutowaredAttribute)); } }
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceB>().As<ITestServiceB>(); #region 注冊所有控制器的關系及控制器實例化所需要的組件 var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes() .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray(); builder.RegisterTypes(controllersTypesInAssembly) .PropertiesAutowired(new PropertySelector()); #endregion }
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { [Autowared] public ITestServiceA TestServiceA { get; set; } public ITestServiceB TestServiceB { get; set; } [HttpGet] public IActionResult Get() { TestServiceA.Show(); TestServiceB.Show(); return Ok(); } }
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceUpdate>().As<ITestServiceA>(); }
如果多個實現同時注冊,則后注冊的實現就會覆蓋先注冊的實現,最后將返回最后一個注冊的實現。
如果多個實現同時注冊,可以通過一個 IEnumerable<實例> 來獲取到所有的實現。
private readonly IEnumerable<ITestServiceA> _testServiceAs; public ValuesController(IEnumerable<ITestServiceA> testServiceAs) { _testServiceAs = testServiceAs; }
當多個實現同時注冊后,可以通過以下方式繼續注冊 實例 的所有實現。從而可以在控制器中直接使用具體實現類作為實現。
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceUpdate>().As<ITestServiceA>(); builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(type => type.IsAssignableTo<ITestServiceA>())); }
private readonly TestServiceA _testServiceA; private readonly TestServiceUpdate _testServiceUpdate; public ValuesController(TestServiceA testServiceA,TestServiceUpdate testServiceUpdate) { _testServiceA = testServiceA; _testServiceUpdate = testServiceUpdate; }
擴展:Autofac 的注冊邏輯可以通過 Module 來拆分管理。
public class AutofacModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { // base.Load(builder); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceUpdate>().As<ITestServiceA>(); builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(type => type.IsAssignableTo<ITestServiceA>())); } }
public void ConfigureContainer(ContainerBuilder builder) { // builder.RegisterModule(new AutofacModule()); builder.RegisterModule<AutofacModule>(); }
AOP 面向切面編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。Autofac 的AOP是通過 Castle(也是一個容器)項目的名為 Autofac.Extras.DynamicProxy 核心部分實現的,顧名思義其實現方式為動態代理。
安裝 NuGet 程序包: Castle.Core 4.4.1
、Autofac.Extras.DynamicProxy 6.0.0
新建自定義 AOP 攔截器
public class CustomAutofacAop : IInterceptor { public void Intercept(IInvocation invocation) { { Console.WriteLine("方法執行前..."); } invocation.Proceed(); { Console.WriteLine("方法執行后..."); } } }
在接口上標記需要使用的攔截器
[Intercept(typeof(CustomAutofacAop))] public interface ITestServiceA { void Show(); }
注冊自定義攔截器,并允許實例接口使用攔截器
public void ConfigureContainer(ContainerBuilder builder) { //builder.RegisterType<CustomAutofacAop>(); builder.RegisterType(typeof(CustomAutofacAop)); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceUpdate>().As<ITestServiceA>().EnableInterfaceInterceptors(); }
在控制器中調用實例,即可成功執行 AOP 攔截器
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private readonly TestServiceA _testServiceA; private readonly TestServiceUpdate _testServiceUpdate; public ValuesController(TestServiceA testServiceA,TestServiceUpdate testServiceUpdate) { _testServiceA = testServiceA; _testServiceUpdate = testServiceUpdate; } public IActionResult Get() { _testServiceA.Show(); _testServiceUpdate.Show(); return Ok(); } }
以上就是“.NET Core中怎么使用Autofac”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。