由于逻辑需要,我希望能在EF Core实例化实体时,拿到实体并执行相关代码,所以我就研究了一番EF Core,得到以下方法。
1.创建实体初始化类,继承EntityMaterializerSource
public class ComBoostEntityMaterializerSource : EntityMaterializerSource { public ComBoostEntityMaterializerSource(IMemberMapper memberMapper) : base(memberMapper) {} }
这个类是,我们需要注入到EF Core当中去的。
2.创建EF Core扩展
public class ComBoostOptionExtension : IDbContextOptionsExtension { public void ApplyServices(IServiceCollection services) { services.AddScoped<IEntityMaterializerSource, ComBoostEntityMaterializerSource>(); } }
创建扩展后,在ApplyServices里注入我们创建的初始化类。
3.用于实例化DbContext时的DbContextOptions参数,需要添加我们创建的扩展
new DbContextOptionsBuilder<DataContext>().UseSqlServer(Configuration.GetConnectionString("DataContext")).Options.WithExtension(new ComBoostOptionExtension()))
4.重写我们的实体初始化类
public class ComBoostEntityMaterializerSource : EntityMaterializerSource { public ComBoostEntityMaterializerSource(IMemberMapper memberMapper, CurrentDatabaseContext current) : base(memberMapper) {
//已注入的,用于业务的获取当前数据库上下文的类 _database = current.Context; } private IDatabaseContext _database;
//创建实例化实体的表达式 public override Expression CreateMaterializeExpression(IEntityType entityType, Expression valueBufferExpression, int[] indexMap = null) {
//获取基类实例化表达式 BlockExpression expression = (BlockExpression)base.CreateMaterializeExpression(entityType, valueBufferExpression, indexMap);
//业务逻辑判断是否是我需要更改的实体 if (typeof(IEntity).IsAssignableFrom(entityType.ClrType)) { var entityContext = _database.GetDynamicContext(entityType.ClrType);
//属性表达式 var property = Expression.Property(expression.Variables[0], typeof(IEntity).GetProperty("EntityContext"));
//赋值表达式 var assign = Expression.Assign(property, Expression.Constant(entityContext));
//把几类的实例化表达式变成列表方便插入 var list = expression.Expressions.ToList();
//因为最后一个表达式是返回实体实例
//所以我们的逻辑代码要放在最后一条语句之前 list.Insert(list.Count - 1, assign);
//重新生成表达式 expression = Expression.Block(expression.Variables, list); } return expression; } }