代码分享.Net6项目下得到指定特性的方法

51 阅读2分钟

在做定时任务模块,将原有的方法,作为定时任务执行,由前台配置定时的时间,这里使用的是特性,就是给方法脑袋上加个[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


那么如何实例化方法调用,并且传参呢,先下班,想起来补;

主要路径如下: