You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何获取作为delegate传递的函数的原始名称

问题描述

你需要实现一个每5分钟触发一次的调度器,对所有每日仅需执行一次的任务做运行状态跟踪,每个作业的上次运行时间存储在静态字典LastRuntimePerJob中,仅当作业当日未运行过时才触发执行。
现有代码无法达到预期:使用nameof(jobToPerform)只会返回参数名"jobToPerform",无法获取传入委托绑定的实际函数名(例如示例中的Job1)。
原有问题代码如下:

using System;
using System.Collections.Generic;
namespace Euler.Business.Problem.Progress
{
    public class Scheduler
    {
        public delegate void JobToPerform();
        public void Job1()
        {
            // Perform some task
        }

        public static Dictionary<string, DateTime> LastRuntimePerJob { get; set; } = new Dictionary<string, DateTime>();

        public void RunScheduler()
        {
            ExecuteWhenNecessary(Job1);
        }

        public void ExecuteWhenNecessary(JobToPerform jobToPerform)
        {
            var nameOfCurrentJob = nameof(jobToPerform);

            if (!LastRuntimePerJob.ContainsKey(nameOfCurrentJob)
            || LastRuntimePerJob[nameOfCurrentJob] < DateTime.Today)
            {
                jobToPerform();
                if (LastRuntimePerJob.ContainsKey(nameOfCurrentJob))
                {
                    LastRuntimePerJob[nameOfCurrentJob] = DateTime.Now;
                }
                else
                {
                    LastRuntimePerJob.Add(nameOfCurrentJob, DateTime.Now);
                }
            }
        }
    }
}
实现方案

C#中所有委托都继承自System.Delegate类型,其内置的Method属性可以获取委托绑定的方法的MethodInfo元数据,直接读取Name属性即可拿到实际绑定的函数名。

核心修改点

将原来获取作业名的代码:

var nameOfCurrentJob = nameof(jobToPerform);

替换为:

var nameOfCurrentJob = jobToPerform.Method.Name;

注意事项

  • 如果传入的委托是多播委托(绑定了多个方法),Method属性只会返回多播列表中最后一个方法的信息,当前调度器场景下每个作业对应单个方法,不会出现这个问题
  • 如果你的调度器需要加载不同类中定义的同名作业,直接用方法名会出现键冲突,可以用$"{jobToPerform.Method.DeclaringType.FullName}.{jobToPerform.Method.Name}"作为唯一键,区分不同类下的同名方法
  • 如果传入的是lambda表达式、匿名方法,获取到的会是编译器生成的带特殊字符的方法名,只要所有注册的作业都是显式定义的具名方法,该方案可以正常工作

修正后完整代码

using System;
using System.Collections.Generic;
namespace Euler.Business.Problem.Progress
{
    public class Scheduler
    {
        public delegate void JobToPerform();
        public void Job1()
        {
            // Perform some task
        }

        public static Dictionary<string, DateTime> LastRuntimePerJob { get; set; } = new Dictionary<string, DateTime>();

        public void RunScheduler()
        {
            ExecuteWhenNecessary(Job1);
        }

        public void ExecuteWhenNecessary(JobToPerform jobToPerform)
        {
            // 从委托元数据中获取实际绑定的方法名
            var nameOfCurrentJob = jobToPerform.Method.Name;

            if (!LastRuntimePerJob.ContainsKey(nameOfCurrentJob)
            || LastRuntimePerJob[nameOfCurrentJob] < DateTime.Today)
            {
                jobToPerform();
                if (LastRuntimePerJob.ContainsKey(nameOfCurrentJob))
                {
                    LastRuntimePerJob[nameOfCurrentJob] = DateTime.Now;
                }
                else
                {
                    LastRuntimePerJob.Add(nameOfCurrentJob, DateTime.Now);
                }
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Vincent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 22:57:21