从零开始写一个领域模型的框架
每篇文章都会打一个对应的 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>(); } } }