DDD 引入Autofac对各层进行解耦,并编写通用的方法拦截器,工作单元,仓储实现

使用 .NET Core 从零开始写一个领域模型的框架

每篇文章都会打一个对应的 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>();
        }

    }
}

 

posted @ 2022-02-05 19:16  乔安生  阅读(329)  评论(0编辑  收藏  举报