随意质疑我的理智。
我需要确定Action<T>
vs Action<T>
是否是原始实例。当我通过抽象方法创建protected Action<T> MessageCallback = null;
时,我所拥有的是具有类变量abstract class Message<T>
的类我强制“他们”初始化MessageCallBack。此MessageCallback被添加到IList<Action<object>>
。此列表中定义的每个操作可以不同。现在,我想要做的是从列表中删除一个特定的操作,但我没有尝试比较它。
以下是我尝试过的最后一次设置的示例:
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)));
}
}
}
我明白我想要做的事情可能是不可能的,但一般来说,我只是做一些不正当的事情或缺乏适当的知识来做这件事,就像我想的那样。提前感谢您提供的任何帮助。
比较它们会一直失败。以下3项建议均无效。我相信我可以改变我处理它的方式,并通过传递一个键然后指向单独的<key, indexOfAction>
列表然后通过索引删除它来使其成为我需要它的工作方式。但是,我觉得我仍然需要付出很大的努力才能解决,所以我将提供更多信息,看看它是否有帮助。
以下是清单:
private readonly IDictionary<Type, IList<Action<object>>> messageReceivedCallbacks;
以下是将操作添加到列表的方式:
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);
}
}
请耐心等待,因为我对这些更高级的编码更新。我可以告诉我,由于new
关键字,我无法进行直接的实例比较。在上面发布的I(第一个)尝试中,我试图让我的回调与添加它的形式相匹配。这是行不通的。我尝试过比较目标,方法,甚至将每种方法转换为其他类型,然后进行比较。
我决定转换我传递的回调,就像它被添加到最后一个aka:
一样var callbackConverted = new Action<object>(m =>
messageReceivedCallback((TMessage)m));
接下来,我使用即时窗口获取一些信息(回调是列表中的回调,callbackConverted是我传入的那个):
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 }
我希望这些额外信息有所帮助。
我发现我让这太复杂了。我需要做的就是添加我的动作,然后从每个字典中删除(唯一的实例)。我正在努力做一些复杂的事情。
目前没有提供任何方法我可以肯定地说,但是我正在标记我认为其他人将使用最佳镜头作为答案。谢谢所有贡献的人。
答案 0 :(得分:7)
您是在谈论找到执行相同操作的操作,还是完全相同的实例? 如果它是完全相同的实例,您可以使用:
messageReceivedCallbacks[callbackType].Remove(messageCallback);
如果要比较方法体,可以执行以下操作:
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);
结果:
没有编译器优化感谢RenniePet's comment
action one vs two: False
action one vs three: True
action one vs four: False
使用编译器优化
action one vs two: True
action one vs three: True
action one vs four: False
但请注意,第一行和第二行之间的比较
答案 1 :(得分:2)
这会有用吗?
messageReceivedCallbacks[callbackType].Remove(messageReceivedCallbacks[callbackType].FirstOrDefault(x => x.Target == messageCallback.Target && x.Method == messageCallback.Method));
答案 2 :(得分:0)
要确定两个委托是否相同,您只需要比较方法和目标对象:
var list = messageReceivedCallbacks[callbackType];
for (var i = list.Count-1; i >= 0; i--)
if (list[i].Method == messageCallback.Method && list[i].Target == messageCallback.Target)
list.RemoveAt(i);