• .NET6.0实现IOC容器


    .NET6.0实现IOC容器

    IOC的作用这里省略…只对如何使用进行说明。

    1. 创建一个.NET6应用程序

    这里使用 .NET6.0 WebAPI 应用

    2. 声明接口

    public interface IAuthService
    {
    bool CheckToken();
    }

    3. 实现接口

    class AuthServiceImpl : IAuthService
    {
    public bool CheckToken()
    {
    Console.WriteLine("check token");
    return true;
    }
    }

    4. 配置IOC容器

    下面是在 program 类中的代码

    var services = new ServiceCollection();
    services.AddSingleton();

    5. 获取服务

    通过在 Controller的构造函数中注入IAuthService

    private readonly IAuthService _service;
    public WeatherForecastController(IAuthService service)
    {
    _service = service;
    }
    [HttpGet(Name = "test")]
    public bool Get()
    {
    return _service.CheckToken();
    }

    启动后,通过swagger发起请求,验证接口。

    基本IOC容器流程已实现。但是这样存在一个弊端,每个接口和实现都要在program中手动注册一遍,还要在Controller构造函数中进行依赖注入,有没有能自动实现注册代替program中的手动注册?

    接下来,对上述流程进行改良。

    6. 改良思路

    定义一个AutowiredAttribute标记,通过Atrribute标记的方式,在实现类上标记其要实现的接口服务,然后实现一个服务加载类ServiceLoader,在这个类中反射获取所有具备AutoIocAttribute的实现类,然后注册到ServiceCollection中。

    6.1 定义特性标记AutowiredAttribute

    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    public class AutowiredAttribute : Attribute
    {
    ///
    /// 接口
    ///
    public Type Iface { get; set; }
    ///
    /// 实现类名
    ///
    public string ImplClassName { get; set; }
    public AutowiredAttribute(Type iface, [CallerMemberName] string implClassName = "")
    {
    Iface = iface;
    ImplClassName = implClassName;
    }
    }

    6.2 实现服务加载类

    利用IServiceCollection作为服务容器

    public class ServiceLoader
    {
    private static object _lock = new object();
    private static AppRuntime _inst;
    private readonly IServiceCollection _iocService = new ServiceCollection();
    private readonly ICollection _iocAssembly = new HashSet();
    private IServiceProvider _iocServiceProvider = null;
    public static ServiceLoader Instance
    {
    get
    {
    if (_inst == null)
    {
    lock (_lock)
    {
    _inst = new ServiceLoader();
    _inst.Startup(typeof(ServiceLoader).Assembly);
    }
    }
    return _inst;
    }
    }
    public T GetService()
    {
    EnsureAutoIoc();
    return _iocServiceProvider.GetService();
    }
    private void EnsureAutoIoc()
    {
    Startup(typeof(T).Assembly);
    }
    public void Startup(Assembly ass)
    {
    if (_iocAssembly.Any(x => x == ass))
    {
    return;
    }
    _iocAssembly.Add(ass);
    var types = ass.GetTypes().Where(x => x.GetCustomAttribute() != null);
    foreach (var item in types)
    {
    var autoIocAtt = item.GetCustomAttribute();
    AddTransient(autoIocAtt.Iface, item);
    }
    //_iocServiceProvider = _iocService.BuildServiceProvider();
    Interlocked.Exchange(ref _iocServiceProvider, _iocService.BuildServiceProvider());
    }
    private void AddTransient(Type iface, Type impl)
    {
    _iocService.AddTransient(iface, impl);
    }
    }

    6.3 在实现类加上标记

    [Autowired(typeof(IAuthService))]
    class AuthServiceImpl : IAuthService
    {
    public bool CheckToken()
    {
    Console.WriteLine("check token");
    return true;
    }
    }

    6.4 在 Controller 中调用

    var svc = ServiceLoader.Instance.GetService();
    svc.CheckToken();

    至此一个基本的完整IOC容器已实现。

  • 相关阅读:
    “先进”的飞书为何搞不定钉钉?
    Hive安装与入门
    mini LED显示屏—点胶测量
    Linux Shell 基础语法 流程控制 逻辑运算 字符串操作详细解析
    logback源码阅读(二)日志打印,自定义appender,encoder,pattern,converter
    设计模式 简单工厂模式的进化过程
    Linux内存管理(四):内存架构和内存模型简述
    webm格式转换成mp4?
    项目实战:组件扫描(2)-获取bean组件存放到IOC容器
    Openjudge1.5答案(十一到十五题)
  • 原文地址:https://www.cnblogs.com/ycit/p/17680238.html