C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web
2021-01-18 06:13
标签:程序 方式 写代码 for line 上下 collect method ret 目录 【微信平台,此文仅授权《NCC 开源社区》订阅号发布】 从前面第四篇开始,进入了实践练习;第五篇实现了实例化一个类型以及对成员方法等的调用。当然,还有一些操作尚将在后面的章节进行介绍。 因为本系列属于实践练习,所以系列文章可能比较多,内容比较长。要学会一种技术,最好的方法是跟着例子代码写一次,运行调试。 本篇文章属于阶段练习,将前面学习到的所有知识点进行总结,实现一个依赖注入功能,仿照 ASP.NET Core 访问 API,自动传递参数以及执行方法,最后返回结果。 本章的代码已上传至 https://gitee.com/whuanle/codes/pby1q6amnzosgkxw830c470 效果: 对用户效果 程序要求效果 写完后的代码大概是这样的 笔者直接在 Program 类里面写了,代码量为 200 行左右(包括详细注释、空白隔行)。 开始编写代码前,请先引入以下命名空间: 在 Program 中,增加以下代码 上面代码的作用是,获取到当前程序的程序集,并且获取元数据信息。 这是反射第一步。 ASP.NET Core 中的路由规则十分丰富,我们自定义各种 URL 规则。主要原理是程序在运行时,将 Controller 、Action 的 [route] 等特性收集起来,生成路由表。 程序执行的基础是类型、方法,ASP.NET Core 中的 Controller 即是 Class,Action 即 Method。 从前面的学习中,我们了解到,通过反射实例化和调用一个类型的成员,只需要确定类型名称、方法名称即可。 对于路由表,我们可以假设(不是指ASP.NET Core的原理)用户访问 URL 时,先从路由表中对比,如果有结果,则将对应的 Class 、Method 拿到手,通过反射机制调用实例化类型调用函数。 这里不实现这么复杂的结构,只实现 Controller-Action 层次的路由。 Program 中,添加一个方法,用于判断当前程序集中是否存在此控制器。 代码非常简单,而且有 Linq 的加持,几行代码就 OK。 实现原理: 判断程序集中是否具有 如果存在,则获取此控制器的 Type 。 Action 是在 Controller 里面的(方法在类型里面),所以我们这里只需要判断以下就行。 实现原理: 判断一个类型中,是否存在 这里不返回 所以这里只做判断,获取 意思是,获取一个类型的构造函数中,所有参数信息,并且为每一个类型实现自动创建实例。 传入参数: 需要进行依赖注入的类型的 Type。 返回数据: 构造函数参数的实例对象列表(反射都是object)。 这里有两个点: ① 对于一个类型来说,可能有多个构造函数; ② 使用 ASP.NET Core 编写一个控制器时,估计没谁会写两个构造函数吧。。。 基于以上两点,我们只要一个构造函数就行,不需要考虑很多情况,我们默认:一个控制器只允许定义一个构造函数,不能定义多个构造函数。 过程实现原理: 获取到构造函数后,接着获取构造函数中的参数列表( 这里又有几个问题 参数是接口类型 参数是正常的 Class 类型 那么,按照以上划分,要考虑的情况更加多了。这里我们根据依赖倒置原则,我们约定,构造函数中的类型,只允许是接口。 因为这里没有 IOC 容器,只是简单的反射实现,所以我们不需要考虑那么多情况(200行代码还想怎么样。。。)。 后面我们查找有哪个类型实现了此接口,就把这个类型实例化做参数传递进去。 注:后面会持续推出更多实战型教程,敬请期待;可以关注微信订阅号 《NCC 开源社区》,获取最新资讯。 目前来到了依赖注入的最后阶段,实例化一个类型、注入依赖、调用方法。 实现原理: 通过 这里确定调用哪个重载方法的方式,是通过参数的多少,因为这里控制台输入只能获取 调用一个方法大概以下几个步骤(不分顺序): 获取类型实例; 获取类型 Type; 获取方法 MethodInfo; 方法的参数对象; 上面代码中,就是实现非常简单的依赖注入过程。 剩下的就是调用方法,通过参数多少去调用相应的重载方法了。 编写一个接口 实现接口 我们按照 ASP.NET Core 写一个控制器的大概形式,实现一个低仿的山寨控制器。 这是常见的依赖注入使用场景: 可以是一个数据库上下文,可以各种类型。 由于控制台输入获取到的是 好吧,我承认我这跟ASP.NET Core没关系,这个这是一个非常简单的功能。 主要就是仿照 StartUp ,实现请求流程和数据返回。 实现过程和原理: C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web 标签:程序 方式 写代码 for line 上下 collect method ret 原文地址:https://www.cnblogs.com/whuanle/p/12181308.html
1,编写依赖注入框架
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
private static Assembly assembly = Assembly.GetCallingAssembly();
private static Type[] types;
static Program()
{
types = assembly.GetTypes();
}
1.1 路由索引
1.1.1 判断控制器 Controller 是否存在
///
{var}Controller
命名的类型,例如 HomeController
。1.1.2 判断 Action 是否存在
///
{actionname}
这个方法。MethodInfo
,而是返回 bool
,是因为考虑到,方法是可以重载的,我们要根据请求时的参数,确定使用哪个方法。MethodInfo
的过程在后面。1.2 依赖实例化
///
ParameterInfo[]
)。
1.3 实例化类型、依赖注入、调用方法
///
CreateType
方法,已经拿到实例化类型的构造函数的参数对象了。string
,更加复杂通过参数类型获取重载方法,可以自行另外测试。 // 获取依赖对象
object[] inject = CreateType(type);
// 注入依赖,实例化对象
object example = Activator.CreateInstance(type, inject);
2,编写控制器和参数类型
2.1 编写类型
///
///
2.2 实现控制器
///
private ITest _test;
public MyClassController(ITest test)
{
_test = test;
}
string
,为了减少麻烦,里面只使用的 Action
方法,参数类型都是 string
。3,实现低配山寨 ASP.NET Core
static void Main(string[] args)
{
while (true)
{
string read = string.Empty;
Console.WriteLine("用户你好,你要访问的控制器(不需要带Controller)");
read = Console.ReadLine();
// 检查是否具有此控制器并且获取 Type
var hasController = IsHasController(read);
// 找不到控制器,报 404 ,让用户重新请求
if (!hasController.Item1)
{
Console.WriteLine("404");
continue;
}
Console.WriteLine("控制器存在,请接着输入要访问的 Action");
read = Console.ReadLine();
// 检查是否具有此 Action 并且获取 Type
bool hasAction = IsHasAction(hasController.Item2, read);
// 找不到,继续报 404
if (hasAction == false)
{
Console.WriteLine("404");
continue;
}
// 目前为止,URL存在,那么就是传递参数了
Console.WriteLine("用户你好,URL 存在,请输入参数");
Console.WriteLine("输入每个参数按一下回车键,结束输入请输入0再按下回车键");
// 开始接收用户输入的参数
List
文章标题:C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web
文章链接:http://soscw.com/index.php/essay/43546.html