第6章 集成第3方依赖注入中间件“Autofac”

news2025/7/19 6:22:55

“Blog.Core-master”示例程序中接口及其具体实现类的注入操作,是通过第3方依赖注入中间件“Autofac”来以反射方式把Service.dll 程序集中所有接口及其具体实现类的实例依赖注入内置容器中。.Net(Core).x框架是中的内置依赖注入容器是不支持程序集注入的

    从最佳实践角度来说,.Net(Core).x框架中的内置容器的功能不如第3方依赖注入中间件“Autofac”强大,但是除非十分必要,不要在基于.Net(Core).x框架的程序中集成 “Autofac”,这虽然使依赖注入的定义相对比较麻烦和出现一些重复性代代码,但简化了整个程序的实现,提升了程序的健壮性和容错性。

 011 MessageModel、MessageModel<T>、BlogViewModels、HtmlHelper、CachingAttribute、IBlogArticleServices、BlogArticleServices、CustomProfile、AutoMapperConfig、AutoMapperSetup、AutofacModuleRegister

MessageModel:把从指定“Api”控制器行方法中获取(指定实体/模型类的所有实例)执行结果及其状态数据信息存储到该类中的属性员中,为客户端页面的渲染提供数据支撑。

       MessageModel<T>:该类以泛型定义形式,把从指定“Api”控制器行方法中获取(指定实体/模型类的所有实例)执行结果及其状态数据信息存储到该类中的属性员中,为客户端页面的渲染提供数据支撑。

说明:

       该类的泛型定义中包含同名的属性成员与方法成员,所以小写了属性成员的第1个字母。

       BlogViewModels:通过该实体类及其属性成员实例,直接为当前程序与前端页面进行数据交互操作及其前端页面的渲染显示提供数据支撑。

HtmlHelper:该类中的方法成员把富文本控件中所显示内容中所包含的“HTML”标签去除后,返回不包含有“HTML”标签的字符串。

CachingAttribute:如果1个方法中的数据被缓存到的分布式数据库中,则在该方法中标记上该特性,就会为所缓存的数据直接设定绝对过期时间,默认值:30(分钟)。

IBlogArticleServices:通过继承于该接口的具体实现类中的方法成员,以异步方式实现了当前程序与“[Blog].[BlogArticle]”表的CURD交互操作。

BlogArticleServices:继承了IBlogArticleServices接口,通过类中的方法成员,以异步方式实现了当前程序与“[Blog].[BlogArticle]”表的CURD交互操作。

using AutoMapper;

using Common.Filter;

using IServices;

using Model.Models;

using Model.ViewModels;

using Services.Base;

namespace Blog.Core.Services

{

    /// <summary>

    /// 【博客文章服务--类】

    /// <remarks>

    /// 摘要:

    ///    通过类中的方法成员,以异步方式实现了当前程序与“[Blog].[BlogArticle]”表的CURD交互操作。

    /// </remarks>

    /// </summary>

    public class BlogArticleServices : BaseServices<BlogArticle>, IBlogArticleServices

    {

        #region 拷贝构造方法与变量

        IMapper _mapper;

        public BlogArticleServices(IMapper mapper)

        {

            this._mapper = mapper;

        }

        #endregion

        #region 方法

        /// <param name="id">1个指定的整型编号值。</param>

        /// <summary>

        /// 【通过编号获取博客文章实例】

        /// <remarks>

        /// 摘要:

        ///    通过1个指定的整型编号值,获取博客视图类的1个指定实例(由“AutoMapper”中间件映射赋值得到)

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    博客视图类的1个指定实例(由于“AutoMapper”中间件映射赋值得到)

        /// </returns>

        /// </summary>

        public async Task<BlogViewModels> GetBlogDetails(int id)

        {

            // 此处想获取上一条下一条数据,因此将全部数据list出来,有好的想法请提出

            //var bloglist = await base.Query(a => a.IsDeleted==false, a => a.bID);

            var blogArticle = (await base.Query(a => a.Id == id && a.Category == "技术博文")).FirstOrDefault();

            BlogViewModels models = null;

            if (blogArticle != null)

            {

                models = _mapper.Map<BlogViewModels>(blogArticle);

                //要取下一篇和上一篇,以当前id开始,按id排序后top(2),而不用取出所有记录

                //这样在记录很多的时候也不会有多大影响

                var nextBlogs = await base.Query(a => a.Id >= id && a.IsDeleted == false && a.Category == "技术博文", 2, "bID");

                if (nextBlogs.Count == 2)

                {

                    models.Next = nextBlogs[1].Title;

                    models.NextId = nextBlogs[1].Id;

                }

                var prevBlogs = await base.Query(a => a.Id <= id && a.IsDeleted == false && a.Category == "技术博文", 2, "bID desc");

                if (prevBlogs.Count == 2)

                {

                    models.Previous = prevBlogs[1].Title;

                    models.PreviousId = prevBlogs[1].Id;

                }

                blogArticle.Traffic += 1;

                await base.Update(blogArticle, new List<string> { "Traffic" });

            }

            return models;

        }

        /// <summary>

        /// 【获取所有博客文章实例】

        /// <remarks>

        /// 摘要:

        ///    获取“[Blog].[BlogArticle]”表中的所有实例,并缓存到分页式缓存数据库中,并设定其设对过期时间为:10(分钟)。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    列表实例,该实例存储着博客文章实体的所有的实例。

        /// </returns>

        /// </summary>

        [Caching(AbsoluteExpiration = 10)]

        public async Task<List<BlogArticle>> GetBlogs()

        {

            var bloglist = await base.Query(a => a.Id > 0, a => a.Id);

            return bloglist;

        }

        #endregion

    }

}

CustomProfile:在实体实例与视图实例进行数据相互赋值操作时,将根据当前类所定义的赋值映射规则,通过“AutoMapper”中间件,实现实体实例与视图实例相互赋值操作。

AutoMapperConfig:该类中的方法成员实例化自定义的赋值映射规则,返回该自定义赋值映射规则实例。

AutoMapperSetup:该类中的方法成员用于把自定义赋值映射规则实例,注入到内置容器中。

using Extensions.AutoMapper;

using Microsoft.Extensions.DependencyInjection;

namespace Extensions.ServiceExtensions

{

    /// <summary>

    /// 【赋值映射规则注入--类】

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     该类中的方法成员用于把自定义赋值映射规则实例,注入到内置容器中。

    /// </remarks>

    public static class AutoMapperSetup

    {

        ///<param name="services">.Net(Core)框架内置依赖注入容器实例。</param>

        /// <summary>

        /// 【添加赋值映射规则注入】

        /// <remarks>

        /// 摘要:

        ///     该方法用于把自定义赋值映射规则实例,注入到内置容器中。

        /// </remarks>

        /// </summary>

        public static void AddAutoMapperSetup(this IServiceCollection services)

        {

            if (services == null) throw new ArgumentNullException(nameof(services));

            //下面的2行语句很好的体现了依赖注入中的依赖倒置关系

            //AddAutoMapper:依赖于Nuget--Model--AutoMapper.Extensions.Microsoft.DependencyInjection

            //把自定义赋值映射规则实例,注入到内置容器中。

            services.AddAutoMapper(typeof(AutoMapperConfig));

            //获取自定义赋值映射规则实例。

            AutoMapperConfig.RegisterMappings();

        }

    }

}

AutofacModuleRegister:通过该类中的方法成员,通过第3方依赖注入中间件把当前程序中所有接口及其具体实现类的实例依赖注入到“Autofac”容器中。

//Nuget--Autofac.Extensions.DependencyInjection

using Autofac;

//Nuget--Autofac.Extras.DynamicProxy

using Autofac.Extras.DynamicProxy;

//using AOP;

using Common.Helper;

using Repository.Base;

using IServices.Base;

using Services.Base;

using Model;

using log4net;

using System;

using System.Collections.Generic;

using System.IO;

using System.Reflection;

using Repository.UnitOfWorks;

namespace Extensions.ServiceExtensions

{

    /// <summary>

    /// 【注册“Autofac”依赖注入--类】

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     通过该类中的方法成员,通过第3方依赖注入中间件把当前程序中所有接口及其具体实现类的实例依赖注入到“Autofac”容器中。

    /// </remarks>

    public class AutofacModuleRegister : Autofac.Module

    {

        private static readonly ILog log = LogManager.GetLogger(typeof(AutofacModuleRegister));

        ///<param name="builder">3方依赖注入中间件“Autofac”依赖注入容器实例。</param>

        /// <summary>

        /// 【依赖注入】

        /// <remarks>

        /// 摘要:

        ///     该方法通过第3方依赖注入中间件“Autofac”来以反射方式把Service.dll 程序集中所有接口及其具体实现类的实例依赖注入到“Autofac”容器中。

        /// </remarks>

        /// </summary>

        protected override void Load(ContainerBuilder builder)

        {

            var basePath = AppContext.BaseDirectory;

            #region 带有接口层的服务注入

            var servicesDllFile = Path.Combine(basePath, "Services.dll");

            var repositoryDllFile = Path.Combine(basePath, "Repository.dll");

            if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))

            {

                var msg = "Repository.dllservice.dll 丢失,因为项目解耦了,所以需要先F6编译,再F5运行,请检查 bin 文件夹,并拷贝。";

                log.Error(msg);

                throw new Exception(msg);

            }

            //用于存储通过第3方依赖注入中间件“Autofac”注入的所有的接口及其具体实现类的类型实例。

            var cacheType = new List<Type>();

            // AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。

            //if (AppSettings.app(new string[] {"AppSettings", "RedisCachingAOP", "Enabled"}).ObjToBool())

            //{

            //    builder.RegisterType<BlogRedisCacheAOP>();

            //    cacheType.Add(typeof(BlogRedisCacheAOP));

            //}

            //if (AppSettings.app(new string[] {"AppSettings", "MemoryCachingAOP", "Enabled"}).ObjToBool())

            //{

            //    builder.RegisterType<BlogCacheAOP>();

            //    cacheType.Add(typeof(BlogCacheAOP));

            //}

            //if (AppSettings.app(new string[] {"AppSettings", "TranAOP", "Enabled"}).ObjToBool())

            //{

            //    builder.RegisterType<BlogTranAOP>();

            //    cacheType.Add(typeof(BlogTranAOP));

            //}

            //if (AppSettings.app(new string[] {"AppSettings", "LogAOP", "Enabled"}).ObjToBool())

            //{

            //    builder.RegisterType<BlogLogAOP>();

            //    cacheType.Add(typeof(BlogLogAOP));

            //}

            //“Autofac”中间件把泛型仓储接口及其具体实现类的实例依赖注入第3“Autofac”容器中。

            builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency();

            //“Autofac”中间件把泛型服务接口及其具体实现类的实例依赖注入第3“Autofac”容器中。

            builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerDependency();//注册服务

            //“Autofac”中间件以反射方式把Service.dll 程序集中所有接口及其具体实现类的实例依赖注入第3“Autofac”容器中。

            var assemblysServices = Assembly.LoadFrom(servicesDllFile);

            builder.RegisterAssemblyTypes(assemblysServices)

                .AsImplementedInterfaces()

                .InstancePerDependency()

                .PropertiesAutowired()

                .EnableInterfaceInterceptors()       //引用Autofac.Extras.DynamicProxy;

                .InterceptedBy(cacheType.ToArray()); //允许将拦截器服务的列表分配给注册。

            //“Autofac”中间件以反射方式把Repository.dll 程序集中所有接口及其具体实现类的实例依赖注入第3“Autofac”容器中。

            var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);

            builder.RegisterAssemblyTypes(assemblysRepository)

                .AsImplementedInterfaces()

                .PropertiesAutowired()

                .InstancePerDependency();

            //“Autofac”中间件把工作单元管量器接口及其具体实现类的实例依赖注入第3“Autofac”容器中。

            builder.RegisterType<UnitOfWorkManage>().As<IUnitOfWorkManage>()

                .AsImplementedInterfaces()

                .InstancePerLifetimeScope()

                .PropertiesAutowired();

            #endregion

            #region 没有接口层的服务层注入

            //因为没有接口层,所以不能实现解耦,只能用 Load 方法。

            //注意如果使用没有接口的服务,并想对其使用 AOP 拦截,就必须设置为虚方法

            //var assemblysServicesNoInterfaces = Assembly.Load("Blog.Core.Services");

            //builder.RegisterAssemblyTypes(assemblysServicesNoInterfaces);

            #endregion

            #region 没有接口的单独类,启用class代理拦截

            //只能注入该类中的虚方法,且必须是public

            //这里仅仅是一个单独类无接口测试,不用过多追问

            //builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Love)))

            //    .EnableClassInterceptors()

            //    .InterceptedBy(cacheType.ToArray());

            #endregion

            #region 单独注册一个含有接口的类,启用interface代理拦截

            //不用虚方法

            //builder.RegisterType<AopService>().As<IAopService>()

            //   .AsImplementedInterfaces()

            //   .EnableInterfaceInterceptors()

            //   .InterceptedBy(typeof(BlogCacheAOP));

            #endregion

        }

    }

}

1 重构Program类

var builder = WebApplication.CreateBuilder(args);

// 把“第3方“Autofac”例依赖注入”中间件实例及其所实例化的接口及具体实现类,依赖注入到.Net(Core)7框架内置容器中。

builder.Host

.UseServiceProviderFactory(new AutofacServiceProviderFactory())

.ConfigureContainer<ContainerBuilder>(builder =>

{

    builder.RegisterModule(new AutofacModuleRegister());

    //builder.RegisterModule<AutofacPropertityModuleReg>();

});

//通过设定的持久化过滤规则及其配置文件(Log4net.config)中的数据实例,实例化第3方“log4net”日志中间件,最后把第3方“log4net”日志中间件依赖注入到内置容器中。

//注意:原示例代码是把把第3方“log4net”日志中间件依赖注入到内置依赖注入第3方“Autofac”容器中。

builder.Services.AddLogging(loging => {

    //第3方“log4net”日志中间件持久化过滤规则:在持久化时,过滤掉带有"System"命名空间的日志信息实例。

    loging.AddFilter("System", LogLevel.Error);

    //第3方“log4net”日志中间件持久化过滤规则:在持久化时,过滤掉带"Microsoft"命名空间的日志信息实例。

    loging.AddFilter("Microsoft", LogLevel.Error);

    loging.SetMinimumLevel(LogLevel.Error);

    loging.AddLog4Net("Log4net.config");

});

//把“AppSettings”实例,依赖注入到.Net(Core)7框架内置容器中。

builder.Services.AddSingleton(new AppSettings(builder.Configuration));

//把“内存缓存”中间件实例,依赖注入到.Net(Core)7框架内置容器中。

builder.Services.AddMemoryCacheSetup();

//把“SqlSugar”中间件实例,依赖注入到.Net(Core)7框架内置容器中。

builder.Services.AddSqlsugarSetup();

//把数据库交互上下文实例,依赖注入到.Net(Core)7框架内置容器中。

builder.Services.AddScoped<MyContext>();

//把带有自定义赋值操作映射规则的“AutoMapper”中间件实例,依赖注入到.Net(Core)7框架内置容器中。

builder.Services.AddAutoMapperSetup();

builder.Services.AddControllers();

    按F5执行程序如下图所示:


   

       对以上功能更为具体实现和注释见:22125_06Blog(集成第3方依赖注入中间件“Autofac”)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/36044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

葡萄糖-聚乙二醇-人血清白蛋白,HAS-PEG-Glucose,人血清白蛋白-PEG-葡萄糖

葡萄糖-聚乙二醇-人血清白蛋白,HAS-PEG-Glucose,人血清白蛋白-PEG-葡萄糖 人血清白蛋白(HSA)是一种高度水溶性的球状单体血浆蛋白&#xff0c;相对分子量为67KDa&#xff0c;由585个氨基酸残基、一个巯基和17个二硫键组成。在纳米颗粒载体中&#xff0c;HSA纳米颗粒与各种药物…

直播预告丨中高频多因子库存储的最佳实践

因子挖掘是量化交易的基础。随着历史交易数据日益增多&#xff0c;交易市场量化竞赛的不断升级和进化&#xff0c;量化投研团队开始面对数据频率高、因子数量多的场景&#xff0c;以10分钟线10000个因子5000个股票为例&#xff0c;一年的因子数据约为 2.3T 左右&#xff0c;1分…

BUUCTF Reverse/firmware

安装工具firmware-mod-kit &#xff0c;可以参考这个firmware-mod-kit工具安装和使用说明 最后make的时候报了个错&#xff0c;参考这个&#xff1a;linux安装firmware-mod-kit /firmware-mod-kit/src/uncramfs/uncramfs.c 加上头文件&#xff1a;#include <sys/sysmacros.h…

想做TikTok跨境电商?如何运营?

想做TikTok跨境电商&#xff1f;如何运营&#xff1f; 据官方报道&#xff1a; 2021年8月TikTok全球月活跃用户数已突破10亿 自2020年7月以来增长了45% 相比2020年初则增长了一倍 月活跃用户能达10亿&#xff0c;覆盖150个国家地区 你只要爆了一条视频 分一小杯羹就能舒…

13.5 GAS与连击

目录1. 连击检测窗口与砍出的第二刀1. 连击检测窗口与砍出的第二刀 连击的实现思路是&#xff0c;在劈砍动画的期间的某一段窗口期&#xff0c;令角色能够再次响应输入&#xff0c;完成伤害动作并进入新的连击动画&#xff0c;直到连招打完。所以核心关键就在于这一段连击窗口…

Halcon机器视觉实战--分水岭分割+距离变换实现粘连物体图像分割

分水岭的原理 把图像的灰度看作高度图,图像中每个像素点的灰度值看作该点的高度,高灰度值代表山脉,低灰度值代表盆地,每个局部最小值及其周围区域称为集水盆,而集水盆的边界则形成分水岭。 分水岭算法的步骤 1.彩色图像转化成单通道灰度图 2.求梯度图 3.在梯度图的基础…

BCH编码译码误码率性能matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 BCH编译码是一种纠错能力强&#xff0c;构造简单的信道编译码。BCH编译码的生成多项式可以由如下的式子表示&#xff1a; ①BCH码是一种纠错码、线性分组码、循环码。 ②需要传输信息位…

如何搭建一个好的知识库管理系统?

简道云知识管理应用对于想知道怎样搭建一个好的知识库管理系统的人来说&#xff0c;拥有正确的流程非常重要。这个过程不需要很复杂&#xff0c;但如果您想要个满足更多需求的知识管理系统&#xff0c;它确实需要非常的全面。 简道云知识库&#xff1a;http://s.fanruan.com/r…

(附源码)计算机毕业设计JavaJava毕设项目社区物业管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

软件测试面试,一定要准备的7个高频面试题(附答案,建议收藏)

收集了2022年最新的面试题后&#xff0c;负责就业的黑马讲师们整理出了7个高频出现的面试题&#xff0c;一起来看看。 高频问题1&#xff1a;请自我介绍下&#xff1f; 高频问题2&#xff1a;请介绍下最近做过的项目&#xff1f; 高频问题3&#xff1a;请介绍下你印象深刻的…

IO模型Netty

一、IO模型 对于一次IO操作&#xff0c;数据会先拷贝到内核空间中&#xff0c;然后再从内核空间拷贝到用户空间中&#xff0c;所以一次read操作&#xff0c;会经历以下两个阶段&#xff0c;基于这两个阶段就产生了五种不同的IO模式。 为了避免用户进程直接操作内核&#xff0c;…

【科学文献计量】RC.networkOneMode()中的参数解释

RC.networkOneMode中的参数解释 1 数据2 RC.networkOneMode()中的参数解释2.1 测试mode参数2.2 测试nodeCount参数2.3 测试edgeWeight参数2.4 测试stemmer参数2.5 测试edgeAttribute参数2.6 测试nodeAttribute参数1 数据 使用web of science中的数据,借助metaknowledge库读入…

跬智信息 (Kyligence) 荣获信创“大比武”重要奖项,坚持做大做实国产软件

近日&#xff0c;为期两个月的 2022 信创“大比武”活动圆满闭幕。经过层层筛选和考核&#xff0c;跬智信息 (Kyligence) 凭借“企业级智能多维数据分析解决方案”项目脱颖而出&#xff0c;在整体方案的技术架构、服务体系、安全架构、信创生态等方面得到了评委的高度认可&…

Python数学基础二、利用正弦sin求曲边图形的面积

目录 正弦 求曲边图形的面积 推导方式解法&#xff1a; 推导式解法&#xff1a; 正弦 古代的勾三股四弦五中说的弦就是我们要说的正弦&#xff0c;也就是直角三角形中的斜边&#xff0c;叫做弦&#xff0c;股就是人的大腿&#xff0c;古人称直角三角形长的那个直角边就叫做…

深入I/O挖矿

1、Linux 系统如何管理文件 1.1 静态文件与 inode 文件在没有被打开的情况下一般都是存放在磁盘中的&#xff0c;譬如电脑硬盘、移动硬盘、U 盘等外部存储设备&#xff0c;文件存放在磁盘文件系统中&#xff0c;并且以一种固定的形式进行存放&#xff0c;我们把他们称为静态文…

二、VSCode——MiKTeX编写latex编码

免安装下载VSCode https://blog.csdn.net/qq_40837795/article/details/128037675 下载MiKTeX https://miktex.org/download 配置MiKTeX https://blog.csdn.net/qq_40837795/article/details/120388489 配置VSCode LaTeX workshop 1、点击左侧Extensions&#xff0c;搜…

论文阅读笔记 | 三维目标检测——VoxelRCNN算法

如有错误&#xff0c;恳请指出。 文章目录1. 背景2. 网络结构Voxel QueryVoxel ROI PoolingAccelerated AggregationLoss Compute3. 实验结果paper&#xff1a;《Voxel R-CNN: Towards High Performance Voxel-based 3D Object Detection》 1. 背景 现有很多的point-based检测…

R语言鸢尾花iris数据集的层次聚类分析

介绍 本文在数据集上展示了如何使用dendextend R软件包来增强Hierarchical Cluster Analysis&#xff08;更好的可视化和灵敏度分析&#xff09;。最近我们被客户要求撰写关于鸢尾花iris的研究报告&#xff0c;包括一些图形和统计输出。 【视频】KMEANS均值聚类和层次聚类&…

从0开始配置深度学习环境(Python)

写这篇文章的起因是因为重装了电脑&#xff0c;之前配好的深度学习环境没了&#xff0c;又在网上找了很久&#xff0c;所以决定记录一下&#xff0c;以备后续刷机。 环境&#xff1a; 显卡&#xff1a;GTX1060 6G CUDA驱动版本&#xff1a;457.20 ——11.1.114 Python版本&…

常用的JVM配置参数说明

工作中常用的JVM参数配置&#xff0c;以Java8为例&#xff1a; 日志相关 -XX:PrintFlagsFinal,打印JVM所有参数的值 -XX:PrintGC,打印GC信息 -XX:PrintGCDetails,打印GC详细信息 -XX:PrintGCTimeStamps,打印GC 的时间戳 -Xloggc:filename,设置GClog文件的位置 -XX:PrintT…