场景:

  前不久,公司里项目经理要求我实现流程处理,比如,用户可以定义一个定时任务,每周一查看报表。定时任务很简单,用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. Apache解析漏洞

    多解析特性 在Apache1.x,2.x中Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断.因此对于apache而言,一个test.php.qwea文件依 ...

  2. Java多线程操作同一个对象,线程不安全

    Java多线程操作同一个对象 发现问题:多个线程操作同一资源的情况下,线程不安全,数据紊乱 代码: package multithreading; // Java多线程操作同一个对象 // 买火车票的 ...

  3. SpringBoot开发十八-显示评论

    需求介绍 显示评论,还是我们之前做的流程. 数据层:根据实体查询一页的评论数据,以及根据实体查询评论的数量 业务层:处理查询评论的业务,处理查询评论数量的业务 表现层:同时显示帖子详情数据时显示该帖子 ...

  4. C++ 基于STL的演讲比赛流程管理系统(sort算法+小型算法(accumulate)+内建函数对象+string字符串拼接+字符串截取+多个容器基础操作+与用户交互+文件的读写+保存+重建+整体文件数据的清空)

    1 /* 2 比赛规则: 3 学校举行一演讲比赛,共12个人参加,比赛两轮,第一轮为淘汰赛 第二轮为决赛 4 每名选手都有对应的编号:如10001~10012 5 比赛方式:分组比赛 每组6人 6 第 ...

  5. 001 PCI Express体系结构(一)

    一 .PCI总线的基本知识 PCI总线作为处理器系统的局部总线,主要目的是为了连接外部设备,而不是作为处理器的系统总线连接Cache和主存储器.但是PCI总线.系统总线和处理器体系结构之间依然存在着紧 ...

  6. Linux搭建VNC servere服务

    此安装方法只适用于centos7以上的版本 一,安装 以root用户运行以下命令来安装vncserver; yum install tigervnc-server  同样运行以下命令来安装vncvie ...

  7. Blazor+Dapr+K8s微服务之开发环境调试

    1         安装Dapr开发调试环境 1.1         Dapr 完整安装模式不支持开发调试 在上一篇随笔<Blazor+Dapr+K8s微服务之服务调用>中,我们通过为每个 ...

  8. Vue-cli UI界面中插件和依赖的区别是什么?

    Vue-cli UI界面中插件和依赖的区别是什么? 先上结论: 插件在命令行中通过 vue add 安装 如: vue add eslint 这个命令将 @vue/eslint 解析为完整的包名 @v ...

  9. TortoiseGit冲突和解决冲突

    产生冲突原因 产生:多个开发者同时使用或者操作git中的同一个文件,最后在依次提交commit和推送push的时候,第一个操作的是可以正常提交的,而之后的开发者想要执行pull(拉)和pull(推)操 ...

  10. mybatis学习日志二

    一.动态sql语句 if语句 if+where语句 if+set语句 choose(when,otherwise)语句 trim语句 sql片段 foreach语句 总结 bean部分的User类代码 ...