1. 程式人生 > 其它 >DDD 引入Autofac對各層進行解耦,並編寫通用的方法攔截器,工作單元,倉儲實現

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>();
        }

    }
}