场景:

  前不久,公司里项目经理要求我实现流程处理,比如,用户可以定义一个定时任务,每周一查看报表。定时任务很简单,用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,实现流程处理的更多相关文章

  1. Quartz系列(一):基础介绍

    新建一个.NET Core控制台项目,NuGet引用Quartz引用. class Program { static void Main(string[] args) { var task = Tas ...

  2. quartz (从原理到应用)详解篇(转)

    一.Quartz 基本介绍 1.1 Quartz 概述 1.2 Quartz特点 1.3 Quartz 集群配置 二.Quartz 原理及流程 2.1 quartz基本原理 2.2 quartz启动流 ...

  3. MFC的消息反射机制

    1.消息反射解释: 父窗口将子窗口发给它的通知消息,首先反射回子窗口进行处理(即给子窗口一个机会,让子窗口处理此消息),这样通知消息就有机会能被子窗口自身进行处理. 2.MFC中引入消息反射的原因: ...

  4. JAVAEE——BOS物流项目13:Quartz概述、创建定时任务、使用JavaMail发送邮件、HighCharts概述、实现区域分区分布图

    1 学习计划 1.Quartz概述 n Quartz介绍和下载 n 入门案例 n Quartz执行流程 n cron表达式 2.在BOS项目中使用Quartz创建定时任务 3.在BOS项目中使用Jav ...

  5. 【java基础】从反射开始(Reflection)

    Java学习笔记 https://github.com/SnailDev/java-learning 和我一起启程... 反射(Reflection) 定义 在运行状态中, 对于任意的一个类,都能够知 ...

  6. Quartz原理解密

    Quartz原理解密 Author: Dorae Date:2018年7月17日15:55:02 转载请注明出处 一.quartz概述 quartz是一个用java实现的开源任务调度框架,可以用来创建 ...

  7. Android 插件化开发(一):Java 反射技术介绍

    写在前面:学习插件化开发推荐书籍<Android 插件化开发指南>,本系列博客所整理知识部分内容出自此书. 在之前的项目架构的博文中,我们提到了项目插件化架构,提到插件化架构不得不提的到J ...

  8. Quartz入门以及相关表达式使用

    目的: 1.Quartz简介及应用场景 2.Quartz简单触发器 SimpleTrigger介绍 3.Quartz表达式触发器CronTirgger介绍 4.Quartz中参数传递 5.Spring ...

  9. spring整合Quartz框架过程,大家可以参考下

    这篇文章详细介绍了spring集成quartz框架流程,通过示例代码进行了详细说明,对学习或任务有参考学习价值,并可供需要的朋友参考. 1.quartz框架简介(m.0831jl.com) quart ...

随机推荐

  1. 全网最硬核Handler面试题深度解析

    1.简述Handler的实现原理 Android 应用是通过消息驱动运行的,在 Android 中一切皆消息,包括触摸事件,视图的绘制.显示和刷新等等都是消息.Handler 是消息机制的上层接口,平 ...

  2. 在CentOS7下的OpenStack中配置使用Spice协议

    在CentOS7下的OpenStack中配置使用Spice协议 by 无若   1. 需要的包 在计算节点上 #yum install spice-html5   注意:使用yum安装spice-ht ...

  3. Java集合框架和数组的排序(转载)

    Java集合框架(*Collection)*和数组的排序 ​ 根据约定,在使用java编程的时候应尽可能的使用现有的类库,当然你也可以自己编写一个排序的方法,或者框架,但是有几个人能写得比JDK里的还 ...

  4. 008 PHY(Physical Layer,PHY)

    一.PHY PHY((Physical Layer,PHY))是IEEE802.3中定义的一个标准模块,STA(station management entity,管理实体,一般为MAC或CPU)通过 ...

  5. 前端从😳 到🚪 gRPC 框架

    RPC 是什么? RPC 英文全称是 Remote Procedure Call 既远程过程调用,维基百科中给的定义是一个计算机调用了一个函数,但这个函数并不在这台计算机上,这种远程调用方式程序员无需 ...

  6. python的基础---常用的正则表达式

    """# 一.re 模块 1.作用:根据规则去匹配字符串 2.表达式:匹配字符串的规则 3.常用方法 findall():[掌握]匹配所有的字符串,把匹配结果作为一个列表 ...

  7. SQL 练习19

    统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] SELECT Course.CId,Course.Cname ,t.[0-60],t.[6 ...

  8. GitLabRunner命令

    启动命令 gitlab-runner --debug <command> #调试模式排查错误特别有用. gitlab-runner <command> --help #获取帮助 ...

  9. zookeeper同一台服务器创建伪集群

    下载zk wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7 ...

  10. java web课程设计(简单商城的前后端双系统,基于maven三模块开发)

    1.系统分析 1.1需求分析 实现一个简单但功能完整的商城项目,从设计到实现,规范化完成该项目,锻炼javaweb项目的编写能力,理解软件工程的软件设计思想 1.2编程技术简介 本次课程主要使用的软件 ...