C# 反射 + Quartz,实现流程处理

2021年09月15日 阅读数:1
这篇文章主要向大家介绍C# 反射 + Quartz,实现流程处理,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

场景:

  前不久,公司里项目经理要求我实现流程处理,好比,用户能够定义一个定时任务,每周一查看报表。定时任务很简单,用Quartz能够实现,可是用户本身选择报表就比较麻烦,由于系统的不一样模块的生成报表的函数不同,因而有了这样的想法:传入一个方法名和方法的输入参数,就能够调用该方法。web

实现:

  这里主要用的是反射的方法。用户要传入方法名和方法参数,咱们就须要先写函数返回这些信息,最后再包装一下返回给用户。api

  获取某一程序集下全部类:(对我来讲,获取当前程序集下的类就够了,要获取其余程序集或dll的,请查询其余资料)ide

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(),来解析出输入类的名称的,应该有其余方法能够拿到输入类的名称:ui

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;
        }

  能够获取输入类的属性类型。spa

建立实例,并执行方法:

  若是是用放射的方式实例化类,很麻烦的是类的构造函数中存在依赖关系。因而我才用依赖注入中获取类的方法。code

  首先,建立一个IServiceProvider的静态类来获取系统依赖注入中的全部服务,再main函数中进行获取和赋值:对象

public static class ServiceHelper
    {
        public static IServiceProvider Instance { get; set; }

    }

  在main中获取依赖注入:blog

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调用接口。