DDD 引入Autofac對各層進行解耦,並編寫通用的方法攔截器,工作單元,倉儲實現
從零開始寫一個領域模型的框架
每篇文章都會打一個對應的 tag
Github 倉庫地址
這版程式碼
使用 Autofac 代替 .NET Core內建的依賴注入框架
使用 Autofac 定義方法攔截器,對指定的方法進行攔截操作
工作單元 (目前只寫了根據id 獲取一條資料的功能)
使用 Autofac 的兩個原因
一、靈活的呼叫某個型別的任意一個構造方法,建立物件
二、自定義方法攔截器
獲取Autofac的IoC容器,ORM物件轉領域物件
Startup.ConfigureContainer // 獲取到 Autofac 的容器 builder.RegisterBuildCallback(scope => { AppSettings.AppAutofacContainer((IContainer)scope); });
public virtual IDomain Find(Guid keyId, bool readOnly = false) { OrmEntity entity = UnitOfWork.CreateSet<OrmEntity>().Find(keyId); // Autofac 獲取到容器之後,可以直接通過指定的引數呼叫相應的建構函式過載,建立例項 IDomain domain = AppSettings.AutofacContainer.Resolve<IDomain>(new NamedParameter("entity", entity));return domain; }
Autofac 自定義方法攔截器
AutofacAOP.cs 攔截器 using Castle.DynamicProxy; using System; using System.Linq; namespace Core2022.Framework.UnitOfWork { public class AutofacAOP : IInterceptor { public void Intercept(IInvocation invocation) { DateTime startTime= DateTime.Now; //objs 是當前攔截方法的入參 object[] objs = invocation.Arguments; invocation.Proceed(); // ret 是當前方法的返回值 object ret = invocation.ReturnValue; DateTime endTime = DateTime.Now; if (invocation.Method.CustomAttributes?.FirstOrDefault(i => i.AttributeType.Name == "AOPLogAttribute") != null) { if (invocation.Method.Name == "Find") // 方法名字 { // 自定義邏輯 } } } } }
AutofacInjectionServicesExtension.cs 註冊攔截器 using Autofac; using Autofac.Extras.DynamicProxy; using Core2022.Framework.Settings; using Core2022.Framework.UnitOfWork; using System; using System.Collections.Generic; using System.Reflection; namespace Core2022.Framework.Commons.Autofac { public static class AutofacInjectionServicesExtension { public static ContainerBuilder AutofacInjectionServices(this ContainerBuilder builder) { foreach (var assemblyString in AppSettings.InjectionServices.AssemblyStrings) { builder.RegisterType<AutofacAOP>(); var assembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + assemblyString); builder.RegisterAssemblyTypes(assembly) .AsImplementedInterfaces() .InstancePerDependency() .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies) .EnableClassInterceptors() .InterceptedBy(new List<Type>().ToArray()); } return builder; } } }
AutofacAOP 用來攔截指定方法的攔截器
把 AutofacAOP 註冊到 Autofac IoC容器中
builder.RegisterType<AutofacAOP>();
.EnableClassInterceptors()
.InterceptedBy(new List<Type>().ToArray());
對指定的方法進行攔截設定
[Intercept(typeof(AutofacAOP))]
public abstract class BaseRepository<IDomain, OrmEntity> : IBaseRepository<IDomain, OrmEntity>
[AOPLog]
public virtual IDomain Find(Guid keyId, bool readOnly = false)
使用
在 AutofacAOP 中的 Intercept 方法中根據引數進行自定義操作
invocation.Method 當前方法的資訊
invocation.Arguments 方法執行前,傳入的引數
invocation.ReturnValue 方法執行後,返回的引數
Autofac 依賴注入
Startup.ConfigureContainer /// <summary> /// Autofac 依賴注入 /// </summary> /// <param name="builder"></param> public void ConfigureContainer(ContainerBuilder builder) { // Autofac 注入Orm物件 builder.AutofacInjectionOrmModel(); // Autofac 注入各層之間的依賴 builder.AutofacInjectionServices(); builder.RegisterBuildCallback(scope => { AppSettings.AppAutofacContainer((IContainer)scope); }); }
using Autofac; using Core2022.Framework.Settings; using System; using System.Reflection; namespace Core2022.Framework.Commons.Autofac { public static class AutofacInjectionOrmModelExtension { public static ContainerBuilder AutofacInjectionOrmModel(this ContainerBuilder builder) { foreach (var assemblyString in AppSettings.InjectionServices.AssemblyStrings) { var assembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + assemblyString); } return builder; } } }
工作單元UnitOfWork
AppUnitOfWork.cs using Core2022.Framework.Settings; using Microsoft.EntityFrameworkCore; namespace Core2022.Framework.UnitOfWork { public class AppUnitOfWork : DbContext, IUnitOfWork { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(AppSettings.ConnectionString); base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { AppSettings.OrmModelInit.ForEach(t => { modelBuilder.Model.AddEntityType(t); }); base.OnModelCreating(modelBuilder); } public DbSet<OrmEntity> CreateSet<OrmEntity>() where OrmEntity : class { return base.Set<OrmEntity>(); } } }