首页 > 其他分享 >关于委托的新认识

关于委托的新认识

时间:2024-04-12 14:33:44浏览次数:22  
标签:调用 Invoke 委托 认识 skillMap private 关于 方法 method

缘由

在技能系统的业务开发中,需要用到一个字符串对应一个方法,我首先想到的就是事件,但我想尝试一下别的

后悔了,平白无故给自己玩坑

数据结构:Dictionary<string, Action>

那如何去初始化它呢

问了ChatGPT,最终的方案是

使用一个SkillManager,其中的每一个方法,就是一个技能,那现在就得到了数据结构中的Value=>Action

然后使用反射去得到方法名,因此就有了第一版

1.0

1.0

private Dictionary<string, MethodInfo> _skillMap;

public SkillManager()
{
    _skillMap = new Dictionary<string, MethodInfo>();
    //获取该类下的private方法
    MethodInfo[] methods = typeof(SkillManager).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (MethodInfo method in methods)
    {
         _skillMap[method.Name] = method;
    }
}

/// <summary>
/// 调用技能方法
/// </summary>
/// <param name="skillName">技能名</param>
/// <returns>技能是否执行成功</returns>
public bool CallSkill(string skillName)
{
    if (_skillMap.TryGetValue(skillName, out MethodInfo method))
    {
        method.Invoke(this, null);
        return true;
    }
    return false;
}

private void TestA() { }
private void TestB() { }
...

 

初次写出来,感觉自己巨牛逼,然后才意识到method.Invoke()要走反射

还有可以优化的地方

于是翻阅互联网,找到如下资料,居然是十年前的

C# 反射的委托创建器 - CYJB - 博客园 (cnblogs.com)

优化2.0

2.0

 private Dictionary<string, Action> _skillMap;

public SkillManager()
{
    _skillMap = new Dictionary<string, Action>();
    //获取该类下的private方法
    MethodInfo[] methods = typeof(SkillManager).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (MethodInfo method in methods)
    {
        if (method.GetParameters().Length == 0 && method.ReturnType == typeof(void))
             _skillMap[method.Name] = (Action)Delegate.CreateDelegate(typeof(Action), this, method);
    }
}

/// <summary>
/// 调用技能方法
/// </summary>
/// <param name="skillName">技能名</param>
/// <returns>技能是否执行成功</returns>
public bool CallSkill(string skillName)
{
    if (_skillMap.TryGetValue(skillName, out Action MethodInfo))
    {
        method.();
        return true;
    }
    return false;
}

private void TestA() { }
private void TestB() { }
...

运行起来倒是都通过了

新玩意儿:

1.MethodInfo.Invoke()

当调用 System.Reflection.RuntimeMethodInfo.Invoke 方法时,它的实现大致可以分为三个主要步骤:

  1. 参数检查: 在执行方法调用之前,Invoke 方法会先对传递的参数进行检查。这包括检查参数数量、类型和是否与目标方法的参数匹配。如果传递的参数与方法的参数不匹配,或者参数的类型无法进行隐式或显式转换,则会抛出相应的异常。此外,如果方法是泛型方法,还会对传递的类型参数进行验证。

  2. 检查 Flags: 在参数检查之后,Invoke 方法会检查调用时传递的 BindingFlags,这些标志指定了要搜索的方法的范围和约束条件,比如是否搜索非公共方法、是否搜索静态方法等。根据传递的 BindingFlags,Invoke 方法会确定需要调用的方法。

  3. 调用方法: 一旦参数检查和标志检查都通过,Invoke 方法会调用 UnsafeInvokeInternal 方法来完成真正的调用过程。在这一步中,会执行实际的方法调用,传递正确的参数,并在调用完成后返回结果。在这个过程中,还会进行安全性检查以确保调用的方法对当前上下文是可访问和可执行的。

在整个过程中,Invoke 方法会处理各种边界情况和异常情况,并确保方法调用能够正确地执行。

2.经过Delegate.CreateDelegate后

简单来说就是变成内存中的实例了,不需要去MetaData或是IL走一圈,也不需要去进行参数和Flags检查了,都规定在Delegate中了

但是!

写了一圈之后,

本来的想法是调用某些具体技能的方法去运行,

结果发现,后续如果需要加技能,那这个类 就会无限扩展下去

还是老老实实用事件吧TAT。

好了,该在项目中把SkillManager删了

标签:调用,Invoke,委托,认识,skillMap,private,关于,方法,method
From: https://www.cnblogs.com/LateUpdate/p/18131141

相关文章

  • 关于工业AI辅助制造(模具设计、模样生产制造环节)
    关于工业AI辅助制造(模具设计、模样生产制造环节)AI技术的具体使用场景:AI辅助模具设计;AI辅助模具安装工艺参数调整。具体方案设想:AI辅助模具设计:使用AI大模型对历史已有的设计方案数据和设计目标数据进行学习,对设计目标和设计方案进行关联并实现在新设计要求的情......
  • Oracle关于半连接SQL执行计划的执行路径一些有趣的实验
     Oracle关于半连接SQL执行计划的执行路径一些有趣的实验 从摩天轮的问答里边看到的一个问题,https://www.modb.pro/issue/34573大概有这么条SQL(包括环境构造语句),如何强制走出nestedloops的执行路径。createtabletb1asselect*fromdba_objects;createtabletb2as......
  • 关于期望 dp 的一点思考
    一、前言只是一些自己的理解,并不知正确与否。首先期望\(dp\)分为伪期望\(dp\)和真期望\(dp.\)二、伪期望\(dp\)对于伪期望\(dp\)来说,其在定义状态之后,一般可以认为状态之间的转移是线性的,即每一个\(dp\)状态转移到何处具有唯一对应性,只不过具体的实现上经过了概......
  • 关于Layui的多层级的下拉选项Select使用教程
    案例代码<selectname="parentSelect"lay-filter="parentSelect"><optionvalue="">请选择父级选项</option><optionvalue="1">父级选项1</option>......
  • 关于git的上传远程仓库的常用命令总结
    我一般上传的步骤:(注意在那个文件夹下打开你要传送的项目)(1)gitinit(2)gitadd.(3)gitcommit-m"上传的项目"(4)与你需要的仓库建立连接gitremoteaddorigin(SSH/HTTPS)(5)gitpush-uoriginmaster/main出现发现远程仓库需要删除的文件下如何进行修改.........
  • 关于配置单机k8s 创建nginx时出现pod 0/1一直pending的情况
    这个事情困扰了我一整天,创建nginx时出现pod0/1pending,一开始是以为flannel网卡出现了问题,一直去选择用calico网卡,但是calico这个玩意配置的路上全是坑,所以一直配不出calico,疯狂重启,疯狂报错,发现flannel网卡没有问题。于是出搜索是怎么回事,删除了nginx重新创建了nginx(这个......
  • 关于分布式的接入的一些问题
      问题一:Ribbon的心跳检测是,对自己缓存的serverlist进行遍历,验证每个服务的状态是否可用,不可用的会被踢出本地缓存?Ribbon的心跳检测是对缓存到本地的服务列表进行的。在这个过程中,Ribbon会遍历本地缓存的ServerList,并对每个服务的状态进行检查,看其是否处于UP状态。这......
  • 关于分布式锁的一些思考
    首先分布式锁要解决的是什么问题?解决的,对唯一资源的操作控制,简单说就是,有一些资源只能同时被一个地方使用。常见的分布式锁的实现方式有哪些?这是一个常见的面试题,一般给出的答案有以下几个:基于数据库的实现方式。可以通过在数据库表中使用排他锁(forupdate)来实现分布式锁,当......
  • (Java)数据结构——排序(第一节)堆排序+PTA L2-012 关于堆的判断
    前言本博客是博主用于复习数据结构以及算法的博客,如果疏忽出现错误,还望各位指正。堆排序(HeapSort)概念堆排序是一种基于堆数据结构的排序算法,其核心思想是将待排序的序列构建成一个最大堆(或最小堆),然后将堆顶元素与最后一个元素交换,再将剩余元素重新调整为最大堆(或最小堆),重复......
  • 关于JSP的MVC设计(新手小白白week7速看)
    通过之前的学习JSP,我们发现我们可以用过Servlet来实现下图功能但是我们发现这样写也太麻烦了吧,而且工程量巨大,所以MVC设计应运而生在开始前,我们需要创建三个软件包,并且创建好我们需要的controller,dao,model相应文件通过需要在WEB-INF中创建目录views,同时把footer,header,i......