C# 反射 + Quartz,实现流程处理
场景:
前不久,公司里项目经理要求我实现流程处理,比如,用户可以定义一个定时任务,每周一查看报表。定时任务很简单,用Quartz可以实现,但是用户自己选择报表就比较麻烦,因为系统的不同模块的生成报表的函数不一样,于是有了这样的想法:传入一个方法名和方法的输入参数,就可以调用该方法。
实现:
这里主要用的是反射的方法。用户要传入方法名和方法参数,我们就需要先写函数返回这些信息,最后再包装一下返回给用户。
获取某一程序集下所有类:(对我来说,获取当前程序集下的类就够了,要获取其他程序集或dll的,请查询其他资料)
public List<string> GetClass(string assembyName = null)
{
Assembly asm = Assembly.GetExecutingAssembly();
var allclass = asm.ExportedTypes.ToList();
return allclass.Select(u => u.Name).ToList();
}
获取某一个类中所有的方法,主要用到GetMethods()的方法:
public List<string> GetMethod(Type type,string assembyName = null)
{
// 测试获取指定类的方法,去除自带的GetType方法
List<MethodInfo> methods = type.GetMethods().Where(u=>u.IsVirtual == false)
.Where(u => !u.Name.Contains("GetType")).ToList();
return methods.Select(u => u.Name).ToList();
}
获取某一个方法的传入参数类型,我是通过把method直接tostring(),来解析出输入类的名称的,应该有其他方法可以拿到输入类的名称:
public List<string> GetParameter(MethodInfo methodInfo, Assembly assembly)
{
// 由方法获取输入类,创建类
var method_FullName = methodInfo.ToString();
// 方法中找不到input类的信息,只能从fullname中解析出来
Regex reg = new Regex(@"(?is)(?<=\()(.*)(?=\))");
Match m = reg.Match(method_FullName);
string inputName = m.Value.Split(".").Last();
Type input_class = assembly.ExportedTypes.Where(u => u.Name.Contains(inputName)).First();
PropertyInfo[] propertyInfos = input_class.GetProperties();
List<string> result = new List<string>();
foreach ( var item in propertyInfos )
{
var returnType = item.GetGetMethod().ReturnType;
var name = returnType.ToString();
result.Add(name);
}
return result;
}
可以获取输入类的属性类型。
创建实例,并执行方法:
如果是用放射的方式实例化类,很麻烦的是类的构造函数中存在依赖关系。于是我才用依赖注入中获取类的方法。
首先,创建一个IServiceProvider的静态类来获取系统依赖注入中的所有服务,再main函数中进行获取和赋值:
public static class ServiceHelper
{
public static IServiceProvider Instance { get; set; } }
在main中获取依赖注入:
public static void Main(string[] args)
{
var webhost = CreateHostBuilder(args).Build();
using ( var scope = webhost.Services.CreateScope() )
{
ServiceHelper.Instance = webhost.Services;
} webhost.Run();
}
这样,就可以避免依赖关系,直接拿依赖注入中的类来反射方法,并执行:
// 获取依赖注入中类
var api = ServiceHelper.Instance.GetService(do_class);
这里的do_class是一个Type。
最后,是使用invoke来执行方法:
PropertyInfo[] propertyInfos = input_class.GetProperties();
Object Args = asm.CreateInstance(input_class.FullName);
foreach ( var item in propertyInfos )
{
var returnType = item.GetGetMethod().ReturnType;
var name = returnType.ToString();
// 匹配类型
if ( name.ToLower().Contains("string") )
{
item.SetValue(Args, "test");
}
else if ( name.ToLower().Contains("int") )
{
item.SetValue(Args, 1);
}
}
// 模拟某方法进行执行
object[] inputArgs = new object[] { Args };
try
{
var result = method.Invoke(api, inputArgs);
}
catch ( Exception ex)
{
Console.WriteLine(ex.Message);
}
这里的Args是通过input类获取的参数类型而设置的实例对象,由于invoke的参数类型为objetc[],所以需要再包装一层。
method是要调用的方法,api是该类的实例,从依赖注入中获取。
最后:
最后就是Quartz的配合,这里就不写了,可以通过JobDataMap来传递参数。再结合HTTP client,可以实现基本流程处理。既可以调用内部函数,也可以http调用接口。
C# 反射 + Quartz,实现流程处理的更多相关文章
- Quartz系列(一):基础介绍
新建一个.NET Core控制台项目,NuGet引用Quartz引用. class Program { static void Main(string[] args) { var task = Tas ...
- quartz (从原理到应用)详解篇(转)
一.Quartz 基本介绍 1.1 Quartz 概述 1.2 Quartz特点 1.3 Quartz 集群配置 二.Quartz 原理及流程 2.1 quartz基本原理 2.2 quartz启动流 ...
- MFC的消息反射机制
1.消息反射解释: 父窗口将子窗口发给它的通知消息,首先反射回子窗口进行处理(即给子窗口一个机会,让子窗口处理此消息),这样通知消息就有机会能被子窗口自身进行处理. 2.MFC中引入消息反射的原因: ...
- JAVAEE——BOS物流项目13:Quartz概述、创建定时任务、使用JavaMail发送邮件、HighCharts概述、实现区域分区分布图
1 学习计划 1.Quartz概述 n Quartz介绍和下载 n 入门案例 n Quartz执行流程 n cron表达式 2.在BOS项目中使用Quartz创建定时任务 3.在BOS项目中使用Jav ...
- 【java基础】从反射开始(Reflection)
Java学习笔记 https://github.com/SnailDev/java-learning 和我一起启程... 反射(Reflection) 定义 在运行状态中, 对于任意的一个类,都能够知 ...
- Quartz原理解密
Quartz原理解密 Author: Dorae Date:2018年7月17日15:55:02 转载请注明出处 一.quartz概述 quartz是一个用java实现的开源任务调度框架,可以用来创建 ...
- Android 插件化开发(一):Java 反射技术介绍
写在前面:学习插件化开发推荐书籍<Android 插件化开发指南>,本系列博客所整理知识部分内容出自此书. 在之前的项目架构的博文中,我们提到了项目插件化架构,提到插件化架构不得不提的到J ...
- Quartz入门以及相关表达式使用
目的: 1.Quartz简介及应用场景 2.Quartz简单触发器 SimpleTrigger介绍 3.Quartz表达式触发器CronTirgger介绍 4.Quartz中参数传递 5.Spring ...
- spring整合Quartz框架过程,大家可以参考下
这篇文章详细介绍了spring集成quartz框架流程,通过示例代码进行了详细说明,对学习或任务有参考学习价值,并可供需要的朋友参考. 1.quartz框架简介(m.0831jl.com) quart ...
随机推荐
- 20分钟掌握Android Gradle
目前国内对Android领域的探索已经越来越深,不少技术领域如插件化.热修复.构建系统等都对Gradle有迫切的需求,不懂Gradle将无法完成上述事情.所以Gradle必须要学习. Gradle 里 ...
- 清晰易懂的RxJava入门实践
导入 我相信大家肯定对ReactiveX 和 RxJava 都不陌生,因为现在只要是和技术相关的网站,博客都会随处见到介绍ReactiveX和RxJava的文章. ReactiveX Reactive ...
- 天梯赛 L2-008 最长对称子串
题目是PTA的天梯赛练习集中的L2-008 https://pintia.cn/problem-sets/994805046380707840/problems/994805067704549376 ...
- SpringMVC学习08(拦截器)
8.拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.开发者可以自己定义一些拦截器来实现特定的功能. 过滤器与拦截器的区别: ...
- 轻松上手SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制实战
前言 我们知道在项目开发中,后台开发权限认证是非常重要的,springboot 中常用熟悉的权限认证框架有,shiro,还有就是springboot 全家桶的 security当然他们各有各的好处,但 ...
- Asp.Net Core 导入Excel数据到Sqlite数据库并重新导出到Excel
Asp.Net Core 导入Excel数据到Sqlite数据库并重新导出到Excel 在博文"在Asp.Net Core 使用 Sqlite 数据库"中创建了ASP.NET Co ...
- 题解 P3643 [APIO2016]划艇
题解 一种思路很好想:\(f_{i,j}\) 表示前 \(i\) 所学校中,第 \(i\) 所学校参赛且派出 \(j\) 艘划艇的方案数.(转移就不列了.) 这种方式有一个致命点,就是 \(j\) 的 ...
- adobe cc 系列产品更改默认安装路径方法
通过Adobe Creative Cloud 修改 1.在开始菜单中找到图下程序点开,并进行如下操作: 2.点击Apps位置 等待加载出软件,如图下所示. 点击右上角图标,会弹出以下窗口,点击首选项 ...
- mysql 常用见的错误处理
一, 创建用户: 命令:CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明:username - 你将创建的用户名, host - 指 ...
- C++ 中的信号的处理
C++ 信号处理 信号是由操作系统传给进程的中断,会提早终止一个程序.在 UNIX.LINUX.Mac OS X 或 Windows 系统上,可以通过按 Ctrl+C 产生中断. 有些信号不能被程序捕 ...