在做定时任务模块,将原有的方法,作为定时任务执行,由前台配置定时的时间,这里使用的是特性,就是给方法脑袋上加个[SysTask] ,在系统启动后 读取全部带SysTask特性的方法,这样就可以在前台展示了。
环境是 .Net6
这里需要 遍历当前解决方案所有的程序集的所有方法,得到包括SysTask特性的方法,然后实例化该类,执行方法;
就是一个遍历, 这里直接写出
public static class AssemblyHelper
{
/// <summary>
/// 返回 指定特性的 方法
/// </summary>
/// <typeparam name="T">特性</typeparam>
/// <returns>
/// <para>context 当前类</para>
/// <para>methodInfo 当前方法</para>
/// <para>attrdata 当前特性</para>
/// <para>constructorArguments 特性的参数</para>
/// <para>namedArguments 特性的属性</para>
/// </returns>
public static IEnumerable<(
Type context, MethodInfo methodInfo,
CustomAttributeData? attrdata,
IList<CustomAttributeTypedArgument>? constructorArguments,
IList<CustomAttributeNamedArgument>? namedArguments)>
GetAttributeMethodInfo<T>()
{
var listassembly = GetAllAssembly();
var listtypes = listassembly.AsParallel()
.Where(m => m!.FullName!.StartsWith("HD")).Select(m => m.GetTypes()).SelectMany(m => m);
foreach (var context in listtypes)
{
var listmethodInfo = context.GetMethods().AsParallel()
.Where(t => t.GetCustomAttributes(typeof(T), false).Length > 0);
foreach (var methodInfo in listmethodInfo)
{
var attrdata = methodInfo.CustomAttributes.Where(t => t.AttributeType == typeof(T))
.FirstOrDefault();
yield return (context, methodInfo,
attrdata,
attrdata?.ConstructorArguments,
attrdata?.NamedArguments);
}
}
}
/// <summary>
/// 得到所有程序集
/// </summary>
/// <returns></returns>
public static IEnumerable<Assembly> GetAllAssembly()
{
var refAssembyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var asslembyNames in refAssembyNames)
{
Assembly.Load(asslembyNames);
}
return AppDomain.CurrentDomain.GetAssemblies();
}
}
使用遍历
/// <summary>
/// 得到所有的任务
/// </summary>
public static void GetAllTasks()
{
AssemblyHelper.GetAttributeMethodInfo<SysTaskAttribute>()
.ToList().ForEach(res =>
{
var context = res.context;//类
var methodInfo = res.methodInfo;//方法
var args = res.constructorArguments;//特性传的参数
});
}
可以注意一下最后两个参数 ,一个是 ConstructorArguments,一个是 NamedArguments
如果特性是这么写的
[AttributeUsage(AttributeTargets.Method)]
public class SysTaskAttribute : Attribute
{
public SysTaskAttribute(string id,string title){}
}
[SysTask(taskGUID, "更新数据源")]
public static void Update(string SourceKey)
{
}
就是普通的重载,那么使用 ConstructorArguments 就可以拿到了,是一个集合 0,1,2... 这么拿,
如果你的特性这么写
[AttributeUsage(AttributeTargets.Method)]
public class SysTaskAttribute : Attribute
{
public string key { get; set; }
}
没有重载,AttributeTargets.Method 是属性可以当参数的意思
那么特性可以这样用
[SysTask(key = taskGUID)]
public static void Update(string SourceKey)
{
}
没有重载时 ConstructorArguments 就拿不到了,要用 最后一个参数 就是 NamedArguments
那么如何实例化方法调用,并且传参呢,先下班,想起来补;
主要路径如下: