前言

一行业务代码还没写,框架代码一大堆,不利于学习。

常看到java的学习资料或博客,标题一般为《SpringBoot 整合 XXX》,所以仿照着写了《.NET 6 整合 Autofac 依赖注入容器》这样一个标题。

以下是我自己的用法,可能不是最佳实践。

一. 引用包

NuGet搜索并安装:

Autofac

Autofac.Extensions.DependencyInjection

二. 配置代码

var builder = WebApplication.CreateBuilder(args);

...省略

// ASP.NET Core整合Autofac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());//通过工厂替换,把Autofac整合进来
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
ServiceFactory.SetBuilder(containerBuilder);
ServiceFactory.RegisterAssembly(Assembly.GetExecutingAssembly()); //注册服务
}); var app = builder.Build(); ServiceFactory.SetContainer((app.Services as AutofacServiceProvider).LifetimeScope as IContainer);
Task.Run(async () => await ServiceFactory.StartAllService()); //启动服务,注意:服务启动完成之前,调用接口会异常 ...省略

三. 服务的自动注册、启动、停止

IService接口

/// <summary>
/// 服务接口
/// </summary>
public interface IService
{
/// <summary>
/// 服务启动
/// </summary>
Task OnStart(); /// <summary>
/// 服务停止
/// </summary>
Task OnStop();
}

RegisterServiceAttribute特性

/// <summary>
/// 注册为服务
/// </summary>
public class RegisterServiceAttribute : Attribute
{
}

ServiceBase抽像类

[RegisterService]
public abstract class ServiceBase : IService
{
#region OnStart
public virtual Task OnStart()
{
return Task.CompletedTask;
}
#endregion #region OnStop
public virtual Task OnStop()
{
return Task.CompletedTask;
}
#endregion }

ServiceFactory服务工厂类

public class ServiceFactory
{
private static ContainerBuilder _builder; private static IContainer _container; private static bool _isRunning; //服务是否正在运行 public static void SetBuilder(ContainerBuilder builder)
{
_builder = builder;
} public static void SetContainer(IContainer container)
{
_container = container;
} /// <summary>
/// Autofac.ContainerBuilder
/// </summary>
public static ContainerBuilder Builder
{
get
{
return _builder;
}
} /// <summary>
/// 获取服务
/// </summary>
/// <typeparam name="T">接口类型</typeparam>
public static T Get<T>()
{
if (_isRunning)
{
return _container.Resolve<T>();
}
else
{
throw new Exception("服务尚未启动完成");
}
} /// <summary>
/// 获取服务
/// </summary>
/// <param name="type">接口类型</param>
public static object Get(Type type)
{
if (_isRunning)
{
return _container.Resolve(type);
}
else
{
throw new Exception("服务尚未启动完成");
}
} #region 注册程序集
/// <summary>
/// 注册程序集
/// </summary>
/// <param name="serviceAssembly">服务程序集</param>
public static void RegisterAssembly(Assembly serviceAssembly)
{
Type[] typeArr = serviceAssembly.GetTypes(); foreach (Type type in typeArr)
{
if (type.GetCustomAttribute<RegisterServiceAttribute>() != null && !type.IsAbstract)
{
_builder.RegisterType(type).SingleInstance().AsImplementedInterfaces().AsSelf();
}
else
{
Type[] interfaceTypes = type.GetInterfaces();
foreach (Type interfaceType in interfaceTypes)
{
if (interfaceType.GetCustomAttribute<RegisterServiceAttribute>() != null && !type.IsAbstract)
{
_builder.RegisterType(type).SingleInstance().AsImplementedInterfaces().AsSelf();
break;
}
}
}
} //_container = _builder.Build();
}
#endregion #region 启动所有服务
/// <summary>
/// 启动所有服务
/// </summary>
public static async Task StartAllService()
{
Type iServiceInterfaceType = typeof(IService);
IEnumerable<Type> types = _container.ComponentRegistry.Registrations.Select(a => a.Activator.LimitType);
await Parallel.ForEachAsync(types, async (type, c) =>
{
if (iServiceInterfaceType.IsAssignableFrom(type))
{
object obj = _container.Resolve(type); try
{
IService service = obj as IService;
await service.OnStart();
LogUtil.Info("服务 " + obj.GetType().FullName + " 已启动");
}
catch (Exception ex)
{
LogUtil.Error(ex, "服务 " + obj.GetType().FullName + " 启动失败");
}
}
});
_isRunning = true;
}
#endregion #region 停止所有服务
/// <summary>
/// 停止所有服务
/// </summary>
public static async Task StopAllService()
{
Type iServiceInterfaceType = typeof(IService);
IEnumerable<Type> types = _container.ComponentRegistry.Registrations.Select(a => a.Activator.LimitType);
await Parallel.ForEachAsync(types, async (type, c) =>
{
if (iServiceInterfaceType.IsAssignableFrom(type))
{
object obj = _container.Resolve(type);
IService service = obj as IService; try
{
await service.OnStop();
LogUtil.Info("服务 " + obj.GetType().FullName + " 已停止");
}
catch (Exception ex)
{
LogUtil.Error(ex, "服务 " + obj.GetType().FullName + " 停止失败");
}
}
});
_isRunning = false;
}
#endregion }

ServiceFactory的简写类

/// <summary>
/// ServiceFactory的简写
/// </summary>
public class SF
{
/// <summary>
/// 获取服务
/// </summary>
/// <typeparam name="T">接口类型</typeparam>
public static T Get<T>()
{
return ServiceFactory.Get<T>();
} /// <summary>
/// 获取服务
/// </summary>
/// <param name="type">接口类型</param>
public static object Get(Type type)
{
return ServiceFactory.Get(type);
}
}

编写服务类

服务类示例1

/// <summary>
/// 测试服务
/// </summary>
public class TestService : ServiceBase
{
public async Task<string> GetValue()
{
return await Task.FromResult("测试数据");
}
}

服务类示例2

重写了OnStart和OnStop以实现服务的启动和停止。

/// <summary>
/// 定时任务管理
/// </summary>
public class ScheduleJobs : ServiceBase
{
#region 变量
private IScheduler _scheduler;
#endregion #region OnStart
public override async Task OnStart()
{
try
{
NameValueCollection options = new NameValueCollection();
string schedulerName = "DefaultQuartzScheduler";
options.Add("quartz.scheduler.instanceName", schedulerName);
StdSchedulerFactory schedulerFactory = new StdSchedulerFactory(options);
_scheduler = await schedulerFactory.GetScheduler(schedulerName);
if (_scheduler == null)
{
_scheduler = await schedulerFactory.GetScheduler();
}
await _scheduler.Start();
AddJobs(_scheduler);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
#endregion #region OnStop
public override async Task OnStop()
{
await _scheduler.Shutdown();
}
#endregion #region ScheduleJob
private async Task ScheduleJob<T>(IScheduler scheduler, string cronString) where T : IJob
{
IJobDetail jobDetail = JobBuilder.Create<T>().Build();
ITrigger trigger = TriggerBuilder.Create().WithCronSchedule(cronString).Build();
await scheduler.ScheduleJob(jobDetail, trigger);
}
#endregion private async void AddJobs(IScheduler scheduler)
{
await ScheduleJob<TestJob>(scheduler, "0/30 * * * * ?");
} }

构造注入示例

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
private readonly TestService _testService; public TestController(TestService testService)
{
_testService = testService;
} ...省略
}

也可以这样使用

var value = await SF.Get<TestService>().GetValue();

.NET 6 整合 Autofac 依赖注入容器的更多相关文章

  1. Autofac依赖注入容器

    依赖注入容器-- Autofac https://github.com/danielpalme/IocPerformance Unity 更新频率高,微软的项目Grace 综合性能更高 目录: 一.简 ...

  2. 依赖注入容器Autofac的详解

    Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成,并且开源,Autofac的主要特性如下: 1,灵活的组件实例化:Aut ...

  3. Asp.Net Core 进阶(三)—— IServiceCollection依赖注入容器和使用Autofac替换它

    Asp.Net Core 提供了默认的依赖注入容器 IServiceCollection,它是一个轻量级的依赖注入容器,所以功能不多,只是提供了基础的一些功能,要实现AOP就有点麻烦,因此在实际工作当 ...

  4. 从零开始,搭建博客系统MVC5+EF6搭建框架(2),测试添加数据、集成Autofac依赖注入

    一.测试仓储层.业务层是否能实现对数据库表的操作 1.创建IsysUserInfoRepository接口来继承IBaseRepository父接口 namespace Wchl.WMBlog.IRe ...

  5. 【干货】利用MVC5+EF6搭建博客系统(二)测试添加数据、集成Autofac依赖注入

    PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.测试仓储层.业务层是否能实现对数据库表的操作 1.在52MVCBlog.IRepository程序集下创建IsysUserInf ...

  6. ASP.NETCore使用AutoFac依赖注入

    原文:ASP.NETCore使用AutoFac依赖注入 实现代码 1.新建接口类:IRepository.cs,规范各个操作类的都有那些方法,方便管理. using System; using Sys ...

  7. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  8. Autofac依赖注入

    简介 Autofac 是一款超赞的.NET IoC 容器 . 它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改 .它的实现方式是将常规的.net类当做 组件 处理. ...

  9. Asp.net core自定义依赖注入容器,替换自带容器

    依赖注入 在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repos ...

  10. WPF PRISM开发入门二(Unity依赖注入容器使用)

    这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点 ...

随机推荐

  1. 升级到 Pulsar3.0 后深入了解 JWT 鉴权

    背景 最近在测试将 Pulsar 2.11.2 升级到 3.0.1的过程中碰到一个鉴权问题,正好借着这个问题充分了解下 Pulsar 的鉴权机制是如何运转的. Pulsar 支持 Namespace/ ...

  2. Mysql不同数据库之间表结构同步

    开发环境的Mysql表结构做了修改,要同步到其他环境数据库中使用数据库管理工具JookDB的表结构同步功能就很方便.虽然Navicat也有这个功能但是有免费的当然是用免费的. 用JookDB添加数据库 ...

  3. jmeter二次开发自定义函数助手

    需求:在工作中,需要使用唯一的字符串来作为订单ID,于是想到了UUID,要求uuid中不能有特殊字符包括横线,所以就有了重新写一个uuid进行使用: 准备:idea 依赖包: 注意事项:必须有包且包的 ...

  4. 深入了解UUID:生成、应用与优势

    一.引言 在当今数字化时代,唯一标识一个对象的能力变得越来越重要.UUID(Universally Unique Identifier,通用唯一标识符)应运而生,作为一种保证全球唯一性的标识方法,广泛 ...

  5. 衡兰芷若成绝响,人间不见周海媚(4k修复基于PaddleGan)

    一代人有一代人的经典回忆,1994年由周海媚.马景涛.叶童主演的<神雕侠侣>曾经风靡一时,周海媚所诠释的周芷若凝聚了汉水之钟灵,峨嵋之毓秀,遇雪尤清,经霜更艳,俘获万千观众,成为了一代人的 ...

  6. 将多个txt文件中的内容写在一个txt中的方法

    import os filename='./train_data/img_' for i in range(1,19736): newfile=filename+str(i)+'.txt' if os ...

  7. 阿里云+智能ai+gpt

    1.阿里 百度 腾讯分词 知识库.     阿里云(项目具体的费用预算展示,实际功能核算.) 向量智库 https://developer.aliyun.com/article/1234278?spm ...

  8. 【内核】基于 LSM 框架的 ELF 校验控制

    欲实现操作系统对正在加载的 ELF 文件的校验控制,需要借助 LSM 框架. LSM 框架介绍 LSM 全称 Linux Security MOdule,是 Linux 的一个安全模块框架.LSM 为 ...

  9. 华企盾DSC造成svn、git连接不上常见处理方法

    1.检查svn服务器是否正在运行 2.检查个人模式连接不上服务器网络加密了客户端未加密(查看客户端日志进程是否为legal:1网络访问设置是否正常,试试只加密服务器IP及端口的方式),个人模式可以连接 ...

  10. npm 发布流程

    登录npm 查看本地是否登录 # 全局配置源 npm who am i # 官方源 npm who am i --registry https://registry.npmjs.org 注: npm源 ...