- A+
所属分类:.NET技术
前言
一行业务代码还没写,框架代码一大堆,不利于学习。
常看到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();