.NET 6整合 autofac 依赖注入容器

前言

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

常看到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 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();