比较代表动作< T> [英] Compare Delegates Action<T>

查看:108
本文介绍了比较代表动作< T>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

随意质疑我的理智

我需要确定一个动作< T> VS 动作< T> 是原来的实例。我所拥有的是一个类变量受保护的动作℃的类; T> MessageCallback = NULL; 我的抽象类信息<时,T> 通过一个抽象的方法创建我强迫他们来初始化MessageCallBack。这MessageCallback被添加到的IList<作用<对象>> 。在此列表中定义的每个动作可以不同。现在,我想要做的就是从列表中删除一个具体行动,但在我尝试比较一下我失败了。

I need to determine if an Action<T> vs Action<T> is the original instance. What I have is a class with a class variable protected Action<T> MessageCallback = null; when my abstract class Message<T> is created via an abstract method I force "them" to initialize the MessageCallBack. This MessageCallback gets added to a IList<Action<object>>. Each action defined in this list can be different. Now, what I want to do is remove a specific action from the list but am failing in my attempts to compare it.

下面是上一次的设置我有一个样本尝试:

Below is a sample of the last setup I have attempted:

public void Unsubscribe<TMessage>(Action<TMessage> messageCallback)
    {
        var messageType = typeof(TMessage);

        var callbackTypes = messageReceivedCallbacks
            .Keys
            .Where(k => k.IsAssignableFrom(messageType));

        lock (messageReceivedCallbacks)
        {
            foreach (var callbackType in callbackTypes)
            {
                messageReceivedCallbacks[callbackType].Remove(new Action<object>(m => 
                    messageCallback((TMessage)m)));
            }
        }
    }



我明白我想这样做是不可能的,但通常我只是做一些不当的方式或缺乏​​适当的知识,做到像我猜想。在此先感谢您提供任何帮助。

I understand what I want to do may not be possible but generally I'm just doing something an improper way or lack proper knowledge to do it like I am suppose to. Thanks in advance for any help you provide.




      • 更新:
          • UPDATE after trying some of the methods below:

          比较它们不停地进行故障。无以下工作目前3建议。我相信我可以改变我是如何处理这并通过传递与再分分离<的名单行动的一个关键是工作,我怎么需要它;键,indexOfAction> 然后通过索引中删除了。不过,我觉得我还需要给这个好功夫来解决,所以我打算给多一点信息,看看是否有帮助。

          Comparing them keeps failing. None of the currently 3 suggestions below work. I do believe I can change how I am handling this and make it work how I need it to by passing in a key with the action that then points to separate list of <key, indexOfAction> then removing that by index. However, I feel like I still need to give this good effort to solve, so I am going to give a little more information to see if it helps.

          下面是清单:

          private readonly IDictionary<Type, IList<Action<object>>> messageReceivedCallbacks;
          

          下面是一个动作如何被添加到列表中:

          Here is how an action gets added to the list:

          void AddMessageReceivedCallback<TMessage>(Action<TMessage> messageReceivedCallback)
              {
                  var intermediateReceivedCallback = new Action<object>(m => 
                      messageReceivedCallback((TMessage)m));
          
                  var receivedList = messageReceivedCallbacks.GetOrCreateValue(typeof(TMessage),
                      () => new List<Action<object>>());
                  lock (receivedList)
                  {
                      receivedList.Add(intermediateReceivedCallback);
                  }
              }
          

          请与我裸露,因为我比较新一些这个更高级的编码。我可以告诉大家这阻止了我这样做,因为关键字直接实例比较。在我的尝试(第一次)公布上述我试图让我的回调,以匹配其加入的形式。这是行不通的。我试过比较对象,方法和每个甚至转换成其他类型,然后进行比较。

          Please bare with me as I am rather new to some of this more advanced coding. I can tell this prevents me from doing a direct instance comparison because of the new keyword. In the attempt I (first) posted above I was trying to get my callback to match the form in which it was added. It does not work. I've tried comparing targets, methods, and even converting each to the others types and then comparing.

          我决定我通过它得到相同的方式转换回调添加到最后又名:

          I decided to convert the callback I pass in the same way it gets added to the last aka:

          var callbackConverted = new Action<object>(m =>
                          messageReceivedCallback((TMessage)m));
          



          接下来,我用即时窗口中只得到一些信息(回调是一个在列表callbackConverted是一个我传递):

          Next, I used the immediate window to just get some information (callback is the one in the list and callbackConverted is the one I pass in):

          callback.Target
          {MessageBus.MessageCoordinator.<Tests.MessageBus.TestMessage>}
              messageReceivedCallback: {Method = {Void <InitializeMessageCallback>b__0(Tests.MessageBus.TestMessage)}}
          
          callback.Method
          {Void <AddMessageReceivedCallback>b__8(System.Object)}
              [System.Reflection.RuntimeMethodInfo]: {Void <AddMessageReceivedCallback>b__8(System.Object)}
              base {System.Reflection.MethodBase}: {Void <AddMessageReceivedCallback>b__8(System.Object)}
              MemberType: Method
              ReturnParameter: {Void }
              ReturnType: {Name = "Void" FullName = "System.Void"}
              ReturnTypeCustomAttributes: {Void }
          
          
          callbackConverted.Target
          {MessageBus.MessageCoordinator.<Tests.MessageBus.TestMessage>}
              messageReceivedCallback: {Method = {Void <InitializeMessageCallback>b__0(Tests.MessageBus.TestMessage)}}
              messageType: {Name = "TestMessage" FullName = "Tests.MessageBus.TestMessage"}
          
          callbackConverted.Method
              {Void <Unsubscribe>b__1d(System.Object)}
                  [System.Reflection.RuntimeMethodInfo]: {Void <Unsubscribe>b__1d(System.Object)}
                  base {System.Reflection.MethodBase}: {Void <Unsubscribe>b__1d(System.Object)}
                  MemberType: Method
                  ReturnParameter: {Void }
                  ReturnType: {Name = "Void" FullName = "System.Void"}
                  ReturnTypeCustomAttributes: {Void }
          

          我希望这些额外的信息可以帮助

          I hope this additional information helps.




              • **更新

              我已经想通了,我正在这太复杂了。所有我需要做的是关键的除了我的行动,那么从每个词典中删除(的唯一实例吧)。我要去我的方式做一些复杂的出路。

              I have figured out that I was making this too complex. All I needed to do was key the addition of my action then remove (the sole instance of it) from each dictionary. I was going way out of my way to do something complex.

              目前没有提供任何方法,我可以肯定地说作品,但我标志着一个我觉得其他人将有使用作为答案的最好的拍摄。谢谢大家谁贡献。

              No method currently provided I can say for sure works but I am marking the one I feel others would have the best shot of using as the answer. Thank you all who contributed.

              推荐答案

              你说的是寻找一个动作,做同样的事情,或者完全相同的实例?
              如果它是你可以使用完全相同的实例:

              Are you talking about finding an action that does the same thing, or the exact same instance? If it's the exact same instance you can just use:

              messageReceivedCallbacks[callbackType].Remove(messageCallback);
              

              如果要比较的方法体,你可以做这样的事情:

              If you want to compare the method bodies, you can do something like this:

              private bool ActionComparer<T>(Action<T> firstAction, Action<T> secondAction)
              {
                  if(firstAction.Target != secondAction.Target)
                      return false;
              
                  var firstMethodBody = firstAction.Method.GetMethodBody().GetILAsByteArray();
                  var secondMethodBody = secondAction.Method.GetMethodBody().GetILAsByteArray();
              
                  if(firstMethodBody.Length != secondMethodBody.Length)
                      return false;
              
                  for(var i = 0; i < firstMethodBody.Length; i++)
                  {
                      if(firstMethodBody[i] != secondMethodBody[i])
                          return false;
                  }
                  return true;
              }
              
              Action<bool> actionOne = (param1) => {return;};
              Action<bool> actionTwo = (param2) => {var i = 1; return;};
              Action<bool> actionThree = (param1) => {return;};
              Action<bool> actionFour = (param2) => {Thread.Sleep(1); return;};
              
              var areEqualOneTwo = ActionComparer(actionOne, actionTwo);
              var areEqualOneThree = ActionComparer(actionOne, actionThree);
              var areEqualOneFour = ActionComparer(actionOne, actionFour);
              
              Console.WriteLine("action one vs two: " + areEqualOneTwo);
              Console.WriteLine("action one vs three: " + areEqualOneThree);
              Console.WriteLine("action one vs four: " + areEqualOneFour);
              



              结果:

              Result:

              没有编译器的优化感谢 RenniePet的评论

              action one vs two: False
              action one vs three: True
              action one vs four: False
              

              使用编译器的优化

              With compiler optimisations

              action one vs two: True
              action one vs three: True
              action one vs four: False
              

              不过请注意,动作一和二

              Note however, the comparison between action one and two

              这篇关于比较代表动作&LT; T&GT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆