通过 C# 中的委托对象识别订阅者对象
Recognize subscriber objects by their Delegate object in C#
我有这个对象:
public class ImageQueueMgr
{
public delegate void OnImageQueueFilledHandler(int imageQueueId);
public event OnImageQueueFilledHandler OnImageQueueFilled;
ReleaseImageQueue(Object obj);
Delegate[] delegateList;
}
其他对象可以订阅此对象事件OnImageQueueFilled
。我希望所有对象都保持订阅状态,但我也想跟踪调用 ReleaseImageQueue(Object obj)
的订阅者,以便我可以在所有订阅者调用后进行一些清理:
ReleaseImageQueue(this)
我知道我可以拥有这样的订阅者列表:
delegateList = OnImageQueueFilled?.GetInvocationList();
所以我的问题是,如何找到与调用 ReleaseImageQueue(this)
的对象对应的委托?
如果我答对了你想从实际事件调用列表的副本中删除委托,你不想取消订阅实际事件。在这种情况下,您可以使用 Delegate.Combine()
方法在另一个事件中复制调用列表。考虑以下代码:
public class ImageQueueMgr
{
public delegate void OnImageQueueFilledHandler(int imageQueueId);
public event OnImageQueueFilledHandler OnImageQueueFilled;
private OnImageQueueFilledHandler _onImageQueueFilledCopy;
private void CopyEventInvocationList()
{
var delegateList = OnImageQueueFilled.GetInvocationList();
_onImageQueueFilledCopy = (OnImageQueueFilledHandler)Delegate.Combine(delegateList);
}
public void NotifyFinish(OnImageQueueFilledHandler finishedHandler)
{
_onImageQueueFilledCopy -= finishedHandler;
}
}
这样,订阅者可以轻松地从调用列表中删除委托,而无需实际取消订阅。请参阅以下使用示例:
public static class Program
{
private static ImageQueueMgr _queueManager = new ImageQueueMgr();
public static void ImageQueuedEventProcessor(int imageQueueId)
{
//some code here
//........
//unsubscribe when done
_queueManager.NotifyFinish(ImageQueuedEventProcessor);
}
public static void ImageQueuedEventProcessor2(int imageQueueId)
{
//some code here
//........
//unsubscribe when done
_queueManager.NotifyFinish(ImageQueuedEventProcessor2);
}
public static void Main()
{
_queueManager.OnImageQueueFilled += ImageQueuedEventProcessor;
_queueManager.OnImageQueueFilled += ImageQueuedEventProcessor2;
}
}
我使用 delegate->Target->Equals
找到了一个解决方案,它在托管 C++ 中,但 C# 等价物非常简单:
List<Delegate^>^ m_delegateList = gcnew List<Delegate^>();
void SetDelegateList(cli::array<Delegate^>^ delegateList)
{
// Convert cli::array to List
for each (Delegate^ delegate in delegateList)
{
m_delegateList->Add(delegate);
}
}
bool RemoveDelegateFromList(System::Object^ obj)
{
Delegate^ delegateToRemove = nullptr;
for each (Delegate^ delegate in m_delegateList)
{
if (delegate->Target->Equals(obj))
{
delegateToRemove = delegate;
exit;
}
}
if (delegateToRemove != nullptr)
{
m_delegateList->Remove(delegateToRemove);
Debug::Print("removed delegate");
}
// If the list of delegates is empty then all of them are done with this image queue
if (m_delegateList->Count == 0)
{
m_mreWaitDone->Set();
}
return false;
}
我有这个对象:
public class ImageQueueMgr
{
public delegate void OnImageQueueFilledHandler(int imageQueueId);
public event OnImageQueueFilledHandler OnImageQueueFilled;
ReleaseImageQueue(Object obj);
Delegate[] delegateList;
}
其他对象可以订阅此对象事件OnImageQueueFilled
。我希望所有对象都保持订阅状态,但我也想跟踪调用 ReleaseImageQueue(Object obj)
的订阅者,以便我可以在所有订阅者调用后进行一些清理:
ReleaseImageQueue(this)
我知道我可以拥有这样的订阅者列表:
delegateList = OnImageQueueFilled?.GetInvocationList();
所以我的问题是,如何找到与调用 ReleaseImageQueue(this)
的对象对应的委托?
如果我答对了你想从实际事件调用列表的副本中删除委托,你不想取消订阅实际事件。在这种情况下,您可以使用 Delegate.Combine()
方法在另一个事件中复制调用列表。考虑以下代码:
public class ImageQueueMgr
{
public delegate void OnImageQueueFilledHandler(int imageQueueId);
public event OnImageQueueFilledHandler OnImageQueueFilled;
private OnImageQueueFilledHandler _onImageQueueFilledCopy;
private void CopyEventInvocationList()
{
var delegateList = OnImageQueueFilled.GetInvocationList();
_onImageQueueFilledCopy = (OnImageQueueFilledHandler)Delegate.Combine(delegateList);
}
public void NotifyFinish(OnImageQueueFilledHandler finishedHandler)
{
_onImageQueueFilledCopy -= finishedHandler;
}
}
这样,订阅者可以轻松地从调用列表中删除委托,而无需实际取消订阅。请参阅以下使用示例:
public static class Program
{
private static ImageQueueMgr _queueManager = new ImageQueueMgr();
public static void ImageQueuedEventProcessor(int imageQueueId)
{
//some code here
//........
//unsubscribe when done
_queueManager.NotifyFinish(ImageQueuedEventProcessor);
}
public static void ImageQueuedEventProcessor2(int imageQueueId)
{
//some code here
//........
//unsubscribe when done
_queueManager.NotifyFinish(ImageQueuedEventProcessor2);
}
public static void Main()
{
_queueManager.OnImageQueueFilled += ImageQueuedEventProcessor;
_queueManager.OnImageQueueFilled += ImageQueuedEventProcessor2;
}
}
我使用 delegate->Target->Equals
找到了一个解决方案,它在托管 C++ 中,但 C# 等价物非常简单:
List<Delegate^>^ m_delegateList = gcnew List<Delegate^>();
void SetDelegateList(cli::array<Delegate^>^ delegateList)
{
// Convert cli::array to List
for each (Delegate^ delegate in delegateList)
{
m_delegateList->Add(delegate);
}
}
bool RemoveDelegateFromList(System::Object^ obj)
{
Delegate^ delegateToRemove = nullptr;
for each (Delegate^ delegate in m_delegateList)
{
if (delegate->Target->Equals(obj))
{
delegateToRemove = delegate;
exit;
}
}
if (delegateToRemove != nullptr)
{
m_delegateList->Remove(delegateToRemove);
Debug::Print("removed delegate");
}
// If the list of delegates is empty then all of them are done with this image queue
if (m_delegateList->Count == 0)
{
m_mreWaitDone->Set();
}
return false;
}