首页 > 其他分享 >简单实现的一个依赖注入框架 (.Net Core7)

简单实现的一个依赖注入框架 (.Net Core7)

时间:2023-06-25 12:22:11浏览次数:40  
标签:框架 serviceCollection value public var new Net Type Core7

根据 Microsoft.Extensions.DepdencyInjection 框架简单仿写的一个 DI 框架。
官方地址:https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.DependencyInjection

测试示例;

using MyDI.Core;

ServiceCollection sc = new ServiceCollection();
sc.AddScoped<IPerson, Student>();
sc.AddSingleton<Student>(new Student("A"));
var provider = sc.Build();

var student = provider.GetService<IPerson>();
student.Say();

var studentA = provider.GetService<Student>();
studentA.Say();

/*
 * output :
 *  Ani is a student.
 *  A is a student.
 */


#region Test Cases

public interface IPerson
{
    public void Say();
}

class Student : IPerson
{
    public Student()
    {
    }

    public Student(string name)
    {
        Name = name;
    }

    public string Name { get; } = "Ani";

    public void Say()
    {
        Console.WriteLine($"{Name} is a student.");
    }
}

#endregion

框架核心代码:

using System.Collections.ObjectModel;

namespace MyDI.Core;

#region Core

public interface IServiceProviderBuilder
{
    public IServiceProvider Build();
}

public class ServiceCollection : Collection<ServiceDescription>, IServiceProviderBuilder
{
    /// <inheritdoc />
    public IServiceProvider Build()
    {
        return new ServiceProvider(this);
    }
}

public static class ServiceCollectionExtensions
{
    public static void AddScoped<T, I>(this ServiceCollection serviceCollection) => serviceCollection.Add(new ServiceDescription(typeof(T), typeof(I)));

    public static void AddSingleton<T>(this ServiceCollection serviceCollection, object? value) => serviceCollection.Add(new ServiceDescription(typeof(T), value?.GetType(), value));
}

public class ServiceProvider : IServiceProvider
{
    private ServiceCollection _serviceCollection;

    public ServiceProvider(ServiceCollection serviceCollection)
    {
        _serviceCollection = serviceCollection;
    }

    /// <inheritdoc />
    public object? GetService(Type serviceType)
    {
        var description = _serviceCollection.FirstOrDefault(t => t.ServiceType == serviceType);
        switch (description)
        {
            case null:
                throw new InvalidOperationException("please register the service type.");
            case { Value: not null }:
                return description.Value;
        }

        var implementType = description.ImplementType;
        var constructorInfos = implementType?.GetConstructors();
        var len = constructorInfos?.Length;
        if (constructorInfos == null || len == 0)
        {
            throw new InvalidOperationException("please provide at least one public constructor.");
        }
        else if (len == 1)
        {
            var constructorInfo = constructorInfos[0];
            var result = constructorInfo.Invoke(null);
            description.Value = result;
            return result;
        }

        var paraments = description.Paraments;
        var paramentsLength = paraments?.Length;
        var constructorInfoT = constructorInfos.FirstOrDefault(t => t.GetParameters().Length == paramentsLength);
        if (constructorInfoT == null)
        {
            constructorInfoT = constructorInfos.FirstOrDefault(t => t.GetParameters().Length == 0);
        }

        if (constructorInfoT == null)
            throw new InvalidCastException("not matched for best constructor.");

        var value = constructorInfoT?.Invoke(paraments);
        description.Value = value;
        return value;
    }
}

public static class ServiceProviderExtensions
{
    public static T GetService<T>(this IServiceProvider provider)
    {
        var result = (T)provider.GetService(typeof(T))!;
        return result;
    }
}

public class ServiceDescription
{
    public ServiceDescription()
    {
    }

    public ServiceDescription(Type serviceType, Type? implementType)
    {
        ServiceType = serviceType;
        ImplementType = implementType;
    }

    public ServiceDescription(Type serviceType, Type? implementType, object? value)
    {
        ServiceType = serviceType;
        ImplementType = implementType;
        Value = value;
    }

    public ServiceDescription(Type serviceType, Type? implementType, object[] paraments, object? value)
    {
        ServiceType = serviceType;
        ImplementType = implementType;
        Paraments = paraments;
        Value = value;
    }

    public Type ServiceType { get; set; }
    public Type? ImplementType { get; set; }
    public object[] Paraments { get; set; } = Array.Empty<object>();
    public object? Value { get; set; }
    public ServiceScope ServiceScope { get; set; }
}

public class ServiceScope
{
}

#endregion

标签:框架,serviceCollection,value,public,var,new,Net,Type,Core7
From: https://www.cnblogs.com/fires/p/17502618.html

相关文章

  • pytest + yaml 框架 -41.postman 和 python代码也能录制成用例
    前言python代码和postman写的接口也能通过录制功能自动生成yaml格式用例了。python代码运行后自动录制环境准备参考前面一篇https://www.cnblogs.com/yoyoketang/p/17495374.html在项目本地新建一个recorde.py,名称随便定义frompytest_yaml_yoyo.mitm_httpimportRecode......
  • 一个亚马逊赞助的.Net轻量级、流行的HTTP客户端库
    我们在实际项目开发中,操作Http请求可以说是非常常见了,这里面就涉及到授权、格式转换、标头参数等,针对不同的项目,我们需要封装一个Http请求帮助类。所以,今天给大家推荐一个Http客户端库,就能完全满足我们的日常需求。 项目简介这是一个基于.Net开发的Http客户端库,它具备序列化......
  • 记一次 .NET 某旅行社审批系统 崩溃分析
    一:背景1.讲故事前些天有位朋友找到我,说他的程序跑着跑着就崩溃了,让我看下怎么回事,其实没怎么回事,抓它的crashdump就好,具体怎么抓也是被问到的一个高频问题,这里再补一下链接:[.NET程序崩溃了怎么抓Dump?我总结了三种方案],采用第二种AEDebug的形式抓取即可。二:Windbg分析1.......
  • ASP.NET Core 6框架揭秘实例演示[40]:基于角色的授权
    ASP.NET应用并没有对如何定义授权策略做硬性规定,所以我们完全根据用户具有的任意特性(如性别、年龄、学历、所在地区、宗教信仰、政治面貌等)来判断其是否具有获取目标资源或者执行目标操作的权限,但是针对角色的授权策略依然是最常用的。角色(或者用户组)实际上就是对一组权限集的描述......
  • TensorFlow10.4 卷积神经网络-ResNet与DenseNet及ResNet实战
    1ResNet我们是实验发现在我们堆叠更多的网络结构的时候,我们并不能又一个很好的结果,就是它网络层次变多了之后他会产生一个多层的loss的堆叠,使得梯度爆炸,或者梯度弥散。然后我们想了一个办法,就是我们比如说设置了一个30层的神经网络,我们在差也不能比22层的差。就是我们设置了一......
  • GoLang图形用户界面编程实战(GUI编程)—fyne框架(三)
    fyne中文乱码的两种解决方法方法一(使用embed):embed是Go1.16新特性,以后会有专门的介绍。1、拷贝字体到项目目录项目根目录下新建resource目录,把字体文件拷贝到其中。2、在resource目录下新建resource_export.go文件。resource_export.go代码:packageresourceimport_"emb......
  • 基于.NetCore开发博客项目 StarBlog - (29) 开发RSS订阅功能
    前言最近忙中偷闲把博客的评论功能给做完了,我可以说这个评论功能已经达到「精致」的程度了......
  • 深度卷积神经网络(AlexNet)
    1.AlexNet\(2012\)年,\(AlexNet\)横空出世。使用\(8\)层卷积神经网络,赢得\(ImageNet\2012\)图像识别挑战赛。\(AlexNet\) 网络结构:1.1第一个卷积层卷积运算:原始数据为\(227\times227\times3\)的图像。卷积核尺寸\(11\times11\times3\),步长\(4\),每次......
  • Python框架Flask
    Flask安装pipinstallFlask项目配置debug模式Host端口号fromflaskimportFlask,requestapp=Flask(__name__)#http://192.168.31.118:5001/@app.route('/')defhello_world():#putapplication'scodeherereturn'HelloWorld12223!&......
  • kubernetes 概述
    1.K8S概述k8s是谷歌在2014年开业的容器化集群管理系统使用k8s进行容器化应用部署使用k8s利于应用扩展k8s目标实施让部署容器化应用更加简洁和高效2.K8S功能(1)自动装箱基于容器对应用运行环境的资源配置要求自动部署应用容器(2)自我修复(自愈能力)当容器失败时,会对容器进行......