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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM