You can use the following methods I wrote to check against existing event subscription. There are some overloads for more or less accurate subscription check.
Note: This only works with instance events and instance event subscription. If the event is subscribed or provided through a static method, this code can't help you since there is no subscriber or/and provider instance to check against.
using System;
using System.Linq;
using System.Reflection;
namespace AnyNamespace
{
/// <summary>
/// Provides extension methods for object types
/// </summary>
public static class ObjectExtender
{
/// <summary>
/// Checks if an event subscription for potential subscriber
/// and its subscription method definition exists
/// </summary>
/// <param name="eventOwnerInstance">
/// The object containing the subscriptions
/// </param>
/// <param name="eventOwnerType">
/// The type which defines the event
/// </param>
/// <param name="eventName">
/// The name of the event on the type which defines it
/// </param>
/// <param name="potentialSubscriber">
/// The potential subscriber to check
/// </param>
/// <param name="subscriptionMethodInfo">
/// The subscription method definition to use as search filter
/// </param>
/// <returns>
/// <c>True</c> if the <c>potentialSubscriber</c> has at least one
/// subscription with the given <c>subscriptionMethodInfo</c>
/// </returns>
static public bool EventSubscriptionExists(this object eventOwnerInstance,
Type eventOwnerType,
string eventName,
object potentialSubscriber,
MethodInfo
subscriptionMethodInfo)
{
return EventSubscriptionExists(eventOwnerType,
eventOwnerInstance,
eventName,
potentialSubscriber,
null,
subscriptionMethodInfo);
}
/// <summary>
/// Checks if an event subscription for potential subscriber
/// and its subscription method name definition exists
/// </summary>
/// <param name="eventOwnerInstance">
/// The object containing the subscriptions
/// </param>
/// <param name="eventOwnerType">
/// The type which defines the event
/// </param>
/// <param name="eventName">
/// The name of the event on the type which defines it
/// </param>
/// <param name="potentialSubscriber">
/// The potential subscriber to check
/// </param>
/// <param name="subscriptionMethodName">
/// The subscription method name to use as search filter
/// </param>
/// <returns>
/// <c>True</c> if the <c>potentialSubscriber</c> has at least
/// one subscription with the given <c>subscriptionMethodName</c>
/// </returns>
/// <remarks>
/// This is a more weak form of method overload
/// (object, Type, string, object, MethodInfo)
/// since it just uses a method name instead a method definition
/// to filter the subscriptions
/// </remarks>
static public bool EventSubscriptionExists(this object eventOwnerInstance,
Type eventOwnerType,
string eventName,
object potentialSubscriber,
string subscriptionMethodName)
{
return EventSubscriptionExists(eventOwnerType,
eventOwnerInstance,
eventName,
potentialSubscriber,
subscriptionMethodName, null);
}
/// <summary>
/// Checks if an event subscription for potential subscriber exists
/// </summary>
/// <param name="eventOwnerInstance">
/// The object containing the subscriptions
/// </param>
/// <param name="eventOwnerType">
/// The type which defines the event
/// </param>
/// <param name="eventName">
/// The name of the event on the type which defines it
/// </param>
/// <param name="potentialSubscriber">
/// The potential subscriber to check
/// </param>
/// <returns>
/// <c>True</c> if the <c>potentialSubscriber</c> has
/// at least one subscription
/// </returns>
static public bool EventSubscriptionExists(this object eventOwnerInstance,
Type eventOwnerType,
string eventName,
object potentialSubscriber)
{
return EventSubscriptionExists(eventOwnerType,
eventOwnerInstance,
eventName,
potentialSubscriber,
null,
null);
}
static bool
EventSubscriptionExists(Type eventOwnerType,
object eventOwnerInstance,
string eventName,
object potentialSubscriber,
string subscriptionMethodName,
MethodInfo
subscriptionMethodInfo)
{
bool ret = false;
var ownerType = eventOwnerType;
if (ownerType.GetEvents().FirstOrDefault(x => x.Name ==
eventName)
is EventInfo eventInfo)
{
var fieldInfoFromEvent = ownerType.GetField(eventInfo.Name,
BindingFlags.NonPublic
|
BindingFlags.Instance
|
BindingFlags.GetField);
var valueFromField = fieldInfoFromEvent.GetValue(eventOwnerInstance);
if (valueFromField is Delegate eventDelegate)
{
ret =
eventDelegate.GetInvocationList()
.Any(x =>
(potentialSubscriber == null
|| potentialSubscriber.Equals(x.Target))
&&
(subscriptionMethodName == null
||
x.Method.Name == subscriptionMethodName)
&& (subscriptionMethodInfo == null
|| subscriptionMethodInfo.Equals(x.Method)));
}
// else:
there are no subscribers at all
}
// else: no
event with given name exists (consider to throw an exception here)
return ret;
}
}
}
Here is a demo how it works:
using System;
namespace AnyNamespace
{
class EventProvider
{
public event EventHandler Event;
}
class EventConsumer
{
private void EventCatcher(object sender, EventArgs e)
{
// foo
;
}
public void SubscribeIfNotIsAlready(EventProvider
eventProvider)
{
// less
accurate check
if
(eventProvider.EventSubscriptionExists(eventProvider.GetType(),
nameof(EventProvider.Event),
this))
{
Console.WriteLine("The eventConsumer has
subscribed to the eventProvider, "
+ "we don't know with which method,
but a subscription exists ...");
}
// more
accurate check
if (eventProvider.EventSubscriptionExists(eventProvider.GetType(),
nameof(EventProvider.Event), this, nameof(EventCatcher)))
{
Console.WriteLine("The eventConsumer has
even subscribed to the eventProvider "
+ "with a method named
'EventCatcher', so we don't need to do it again ...");
}
else
{
Console.WriteLine("There was no subscription
by 'EventCatcher' for this event, "
+"we add now ..");
eventProvider.Event +=
EventCatcher;
}
}
}
class Program
{
static EventProvider eventProvider = new EventProvider();
static EventConsumer eventConsumer = new EventConsumer();
static void Main(string[] args)
{
Console.WriteLine("1. Imagine this code is not known by us and it conditionally
"
+ "adds a subscription to an
event.");
eventConsumer.SubscribeIfNotIsAlready(eventProvider);
Console.WriteLine("2. Now we continue
without knowning if we still need to add "
+ "a subscription to the specified
event.");
DoSomething();
Console.ReadKey();
}
static void DoSomething()
{
/* assume,
that we don't know if the event is already subscribed:
* maybe, because the class is
partial or, or, or whyever
*/
eventConsumer.SubscribeIfNotIsAlready(eventProvider);
}
}
}