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().Find(keyId);
   // Autofac 获取到容器之后,可以直接通过指定的参数调用相应的构造函数重载,创建实例
    IDomain domain = AppSettings.AutofacContainer.Resolve(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();
                var assembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + assemblyString);
                builder.RegisterAssemblyTypes(assembly)
                    .AsImplementedInterfaces()
                    .InstancePerDependency()
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .EnableClassInterceptors()
                    .InterceptedBy(new List().ToArray());
            }

            return builder;
        }
    }
}

AutofacAOP 用来拦截指定方法的拦截器

把 AutofacAOP 注册到 Autofac IoC容器中

  builder.RegisterType();

  .EnableClassInterceptors()

  .InterceptedBy(new List().ToArray());

对指定的方法进行拦截设置

  [Intercept(typeof(AutofacAOP))]

  public abstract class BaseRepository : IBaseRepository

  [AOPLog]

  public virtual IDomain Find(Guid keyId, bool readOnly = false)

使用

  在 AutofacAOP 中的 Intercept 方法中根据参数进行自定义操作

  invocation.Method 当前方法的信息

  invocation.Arguments 方法执行前,传入的参数

  invocation.ReturnValue 方法执行后,返回的参数

Autofac 依赖注入

Startup.ConfigureContainer

/// 
/// Autofac 依赖注入
/// 
/// 
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 CreateSet()
          where OrmEntity : class
        {
            return base.Set();
        }

    }
}