• .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容器已实现。

  • 相关阅读:
    手机桌面待办事项APP推荐
    CSS 实现:常见布局
    视频翻译字幕的软件哪个好?看完你就知道了
    基于变化点 copula 优化算法中的贝叶斯研究(Matlab代码实现)
    Golang操作sqlite3数据库教程
    ACCESS_MASK不明确的符号
    接口测试面试题整理​​​​​​​
    Linux基本指令(下)——“Linux”
    计算机系统的基本概念
    箭头函数和普通函数的区别
  • 原文地址:https://www.cnblogs.com/ycit/p/17680238.html