前言
一行业务代码还没写,框架代码一大堆,不利于学习。
常看到java的学习资料或博客,标题一般为《SpringBoot 整合 XXX》,所以仿照着写了《.NET 6 整合 Autofac 依赖注入容器》这样一个标题。
以下是我自己的用法,可能不是最佳实践。.
一. 引用包
NuGet搜索并安装:
Autofac
Autofac.Extensions.DependencyInjection
二. 配置代码
var builder = WebApplication.CreateBuilder(args);...省略// ASP.NET Core整合Autofacbuilder.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 OnStartpublic virtual Task OnStart(){return Task.CompletedTask;}#endregion#region OnStoppublic 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 OnStartpublic 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 OnStoppublic override async Task OnStop(){await _scheduler.Shutdown();}#endregion#region ScheduleJobprivate 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);}#endregionprivate 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();