场景:

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

最新文章

  1. 强大的swift字符串
  2. 探讨Nodejs中的作用域问题。
  3. SQL Server发布订阅功能研究
  4. eclipse svn proxy
  5. VR教育旋风来袭,各大公司争先进军虚拟现实教育
  6. SQL Server执行计划的理解【转】
  7. ML 04、模型评估与模型选择
  8. Codeforces Round #343 (Div. 2) B. Far Relative’s Problem
  9. mac install php dev
  10. STK 10.1.3
  11. Hibernate 报错:this project is not a myeclipse hibernate project . assuming hibernate 3 cap
  12. apache2.4.x三种MPM介绍
  13. 使用反射动态调用ActiveX控件
  14. winform Combobox出现System.Data.DataRowView的解决的方法
  15. 【原创】Python第二章——行与缩进
  16. redis设置防火墙的问题
  17. poj 2955&quot;Brackets&quot;(区间DP)
  18. MySQL数据库(增删查改)
  19. itsdangerous
  20. 3、zookeeper 集群模式搭建

热门文章

  1. 防火墙和SElinux简单配置
  2. 并发编程——线程中sleep(),yield(),join(),wait(),notify(),notifyAll()区别
  3. Java代码编写、代码优化技巧总结
  4. DrJava试用笔记
  5. mac 软件意外退出
  6. Redis内存碎片
  7. NOIP 模拟 6 考试总结
  8. 设置一个元素的HTML内容
  9. mfc HackerTools远程线程注入
  10. await 关键字 后面跟Task 和Task &lt;T&gt;