Guest User

EventAggregator.cs

a guest
Apr 16th, 2023
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 24.30 KB | None | 0 0
  1. namespace BionicCode.Utilities.Net
  2. {
  3.   #region Info
  4.   // //  
  5.   // BionicUtilities.Net.Standard
  6.   #endregion
  7.  
  8.   using System;
  9.   using System.Collections.Concurrent;
  10.   using System.Collections.Generic;
  11.   using System.Linq;
  12.   using System.Reflection;
  13.   using System.Runtime.CompilerServices;
  14.   using System.Threading;
  15.   using BionicCode.Utilities.Net;
  16.  
  17.   /// <inheritdoc />
  18.   public class EventAggregator : IEventAggregator
  19.   {
  20.     /// <summary>
  21.     /// Default constructor.
  22.     /// </summary>
  23.     public EventAggregator()
  24.     {
  25.       this.EventHandlerTable = new ConcurrentDictionary<string, List<Delegate>>();
  26.       this.EventHandlerSynchronizationContextTable = new ConcurrentDictionary<Delegate, SynchronizationContext>();
  27.       this.EventPublisherTable = new ConditionalWeakTable<object, List<(EventInfo EventInfo, Delegate Handler)>>();
  28.     }
  29.  
  30.     #region Implementation of IEventAggregator
  31.  
  32.     /// <inheritdoc />
  33.     public bool TryRegisterObservable(object eventSource, IEnumerable<string> eventNames)
  34.     {
  35.       if (object.Equals(eventSource, default))
  36.       {
  37.         return false;
  38.       }
  39.       foreach (string eventName in eventNames.Distinct())
  40.       {
  41.         EventInfo eventInfo = eventSource.GetType()
  42.           .GetEvent(
  43.             eventName,
  44.             BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  45.         if (eventInfo == null)
  46.         {
  47.           throw new ArgumentException($"The event {eventName} was not found on the event source {eventSource.GetType().Name} or on its declaring base type.");
  48.         }
  49.  
  50.         Type normalizedEventHandlerType = NormalizeEventHandlerType(eventInfo.EventHandlerType);
  51.         ICollection<string> eventIds = CreateEventIdsOfConcreteType(eventSource, normalizedEventHandlerType, eventName);
  52.  
  53.         if (TryCreateEventIdOfInterfaceType(eventSource, eventName, out string interfaceEventId))
  54.         {
  55.           eventIds.Add(interfaceEventId);
  56.         }
  57.  
  58.         (Type EventHandlerType, ICollection<string> EventIds) eventIdArg = (normalizedEventHandlerType, eventIds);
  59.  
  60.         Action<object, object> clientHandlerInvocator = (sender, args) => DelegateHandleEvent(eventIdArg, sender, args);
  61.         var eventSourceHandler = Delegate.CreateDelegate(
  62.           eventInfo.EventHandlerType,
  63.           clientHandlerInvocator.Target,
  64.           clientHandlerInvocator.Method);
  65.  
  66.         List<(EventInfo EventInfo, Delegate Handler)> publishers = this.EventPublisherTable.GetOrCreateValue(eventSource);
  67.         publishers.Add((eventInfo, eventSourceHandler));
  68.        
  69.         eventInfo.AddEventHandler(eventSource, eventSourceHandler);
  70.       }
  71.  
  72.       return true;
  73.     }
  74.  
  75.     /// <inheritdoc />
  76.     public bool TryRemoveObservable(object eventSource, IEnumerable<string> eventNames, bool removeEventObservers = false)
  77.     {
  78.       bool hasRemovedObservable = false;
  79.       if (!this.EventPublisherTable.TryGetValue(eventSource, out List<(EventInfo EventInfo, Delegate Handler)> publisherHandlerInfos))
  80.       {
  81.         return false;
  82.       }
  83.       foreach (string eventName in eventNames)
  84.       {
  85.         (EventInfo EventInfo, Delegate Handler) publisherHandlerInfo = publisherHandlerInfos.FirstOrDefault(
  86.           handlerInfo => handlerInfo.EventInfo.Name.Equals(eventName, StringComparison.Ordinal));
  87.  
  88.         publisherHandlerInfo.EventInfo?.RemoveEventHandler(eventSource, publisherHandlerInfo.Handler);
  89.         hasRemovedObservable = publisherHandlerInfos.Remove(publisherHandlerInfo);
  90.  
  91.         if (removeEventObservers)
  92.         {
  93.           TryRemoveAllObservers(eventName, eventSource.GetType());
  94.         }
  95.       }
  96.  
  97.       if (!publisherHandlerInfos.Any())
  98.       {
  99.         this.EventPublisherTable.Remove(eventSource);
  100.       }
  101.  
  102.       return hasRemovedObservable;
  103.     }
  104.  
  105.     /// <inheritdoc />
  106.     public bool TryRemoveObservable(object eventSource, bool removeObserversOfEvents = false)
  107.     {
  108.       bool hasRemovedObservable = false;
  109.  
  110.       if (this.EventPublisherTable.TryGetValue(eventSource, out List<(EventInfo EventInfo, Delegate Handler)> handlerInfo))
  111.       {
  112.         this.EventPublisherTable.Remove(eventSource);
  113.  
  114.         handlerInfo.ForEach(publisherHandlerInfo => publisherHandlerInfo.EventInfo.RemoveEventHandler(eventSource, publisherHandlerInfo.Handler));
  115.         hasRemovedObservable = true;
  116.       }
  117.  
  118.       if (removeObserversOfEvents)
  119.       {
  120.         TryRemoveAllObservers(eventSource.GetType());
  121.       }
  122.  
  123.       return hasRemovedObservable;
  124.     }
  125.  
  126.     /// <inheritdoc />
  127.     public bool TryRegisterObserver(string eventName, Type eventSourceType, Delegate eventHandler)
  128.     {
  129.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfSpecificSource(eventSourceType, eventName);
  130.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  131.     }
  132.  
  133.     /// <inheritdoc />
  134.     public bool TryRegisterObserver(string eventName, Type eventSourceType, Delegate eventHandler, bool isMarshalEventToCurrentThreadEnabled)
  135.     {
  136.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfSpecificSource(eventSourceType, eventName);
  137.       return isMarshalEventToCurrentThreadEnabled
  138.         ? TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, SynchronizationContext.Current)
  139.         : TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  140.     }
  141.  
  142.     /// <inheritdoc />
  143.     public bool TryRegisterObserver(string eventName, Type eventSourceType, Delegate eventHandler, SynchronizationContext synchronizationContext)
  144.     {
  145.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfSpecificSource(eventSourceType, eventName);
  146.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, synchronizationContext);
  147.     }
  148.  
  149.     /// <inheritdoc />
  150.     public bool TryRegisterObserver<TEventArgs>(string eventName, Type eventSourceType, EventHandler<TEventArgs> eventHandler)
  151.       => TryRegisterObserver(eventName, eventSourceType, (Delegate) eventHandler);
  152.  
  153.     /// <inheritdoc />
  154.     public bool TryRegisterObserver<TEventArgs>(string eventName, Type eventSourceType, EventHandler<TEventArgs> eventHandler, bool isMarshalEventToCurrentThreadEnabled)
  155.       => TryRegisterObserver(eventName, eventSourceType, (Delegate)eventHandler, isMarshalEventToCurrentThreadEnabled);
  156.  
  157.     /// <inheritdoc />
  158.     public bool TryRegisterObserver<TEventArgs>(string eventName, Type eventSourceType, EventHandler<TEventArgs> eventHandler, SynchronizationContext synchronizationContext)
  159.       => TryRegisterObserver(eventName, eventSourceType, (Delegate)eventHandler, synchronizationContext);
  160.  
  161.     /// <inheritdoc />
  162.     public bool TryRegisterGlobalObserver(string eventName, Delegate eventHandler)
  163.     {
  164.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  165.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  166.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  167.     }
  168.  
  169.     /// <inheritdoc />
  170.     public bool TryRegisterGlobalObserver(string eventName, Delegate eventHandler, bool isMarshalEventToCurrentThreadEnabled)
  171.     {
  172.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  173.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  174.       return isMarshalEventToCurrentThreadEnabled
  175.          ? TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, SynchronizationContext.Current)
  176.          : TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  177.     }
  178.  
  179.     /// <inheritdoc />
  180.     public bool TryRegisterGlobalObserver(string eventName, Delegate eventHandler, SynchronizationContext synchronizationContext)
  181.     {
  182.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  183.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  184.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, synchronizationContext);
  185.     }
  186.  
  187.     /// <inheritdoc />
  188.     public bool TryRegisterGlobalObserver<TEventArgs>(string eventName, EventHandler<TEventArgs> eventHandler)
  189.     {
  190.       Type normalizedEventHandlerType = NormalizeEventHandlerType<TEventArgs>(eventHandler.GetType());
  191.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  192.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  193.     }
  194.  
  195.     /// <inheritdoc />
  196.     public bool TryRegisterGlobalObserver<TEventArgs>(string eventName, EventHandler<TEventArgs> eventHandler, bool isMarshalEventToCurrentThreadEnabled)
  197.     {
  198.       Type normalizedEventHandlerType = NormalizeEventHandlerType<TEventArgs>(eventHandler.GetType());
  199.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  200.       return isMarshalEventToCurrentThreadEnabled
  201.          ? TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, SynchronizationContext.Current)
  202.          : TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  203.     }
  204.  
  205.     /// <inheritdoc />
  206.     public bool TryRegisterGlobalObserver<TEventArgs>(string eventName, EventHandler<TEventArgs> eventHandler, SynchronizationContext synchronizationContext)
  207.     {
  208.       Type normalizedEventHandlerType = NormalizeEventHandlerType<TEventArgs>(eventHandler.GetType());
  209.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  210.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, synchronizationContext);
  211.     }
  212.  
  213.     /// <inheritdoc />
  214.     public bool TryRegisterGlobalObserver(Delegate eventHandler)
  215.     {
  216.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  217.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  218.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  219.     }
  220.  
  221.     /// <inheritdoc />
  222.     public bool TryRegisterGlobalObserver(Delegate eventHandler, bool isMarshalEventToCurrentThreadEnabled)
  223.     {
  224.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  225.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  226.       return isMarshalEventToCurrentThreadEnabled
  227.          ? TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, SynchronizationContext.Current)
  228.          : TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  229.     }
  230.  
  231.     /// <inheritdoc />
  232.     public bool TryRegisterGlobalObserver(Delegate eventHandler, SynchronizationContext synchronizationContext)
  233.     {
  234.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  235.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  236.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, synchronizationContext);
  237.     }
  238.  
  239.     /// <inheritdoc />
  240.     public bool TryRegisterGlobalObserver<TEventArgs>(EventHandler<TEventArgs> eventHandler)
  241.     {
  242.       Type normalizedEventHandlerType = NormalizeEventHandlerType<TEventArgs>(eventHandler.GetType());
  243.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  244.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  245.     }
  246.  
  247.     /// <inheritdoc />
  248.     public bool TryRegisterGlobalObserver<TEventArgs>(EventHandler<TEventArgs> eventHandler, bool isMarshalEventToCurrentThreadEnabled)
  249.     {
  250.       Type normalizedEventHandlerType = NormalizeEventHandlerType<TEventArgs>(eventHandler.GetType());
  251.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  252.       return isMarshalEventToCurrentThreadEnabled
  253.          ? TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, SynchronizationContext.Current)
  254.          : TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName);
  255.     }
  256.  
  257.     /// <inheritdoc />
  258.     public bool TryRegisterGlobalObserver<TEventArgs>(EventHandler<TEventArgs> eventHandler, SynchronizationContext synchronizationContext)
  259.     {
  260.       Type normalizedEventHandlerType = NormalizeEventHandlerType<TEventArgs>(eventHandler.GetType());
  261.       var fullyQualifiedEventName = CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  262.       return TryRegisterObserverInternal(eventHandler, fullyQualifiedEventName, synchronizationContext);
  263.     }
  264.  
  265.     /// <inheritdoc />
  266.     public bool TryRemoveObserver(string eventName, Type eventSourceType, Delegate eventHandler)
  267.     {
  268.       string fullyQualifiedEventIdOfSpecificSource =
  269.         CreateFullyQualifiedEventIdOfSpecificSource(eventSourceType, eventName);
  270.       this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  271.       return this.EventHandlerTable.TryRemove(fullyQualifiedEventIdOfSpecificSource, out _);
  272.     }
  273.  
  274.     /// <inheritdoc />
  275.     public bool TryRemoveObserver<TEventArgs>(
  276.       string eventName,
  277.       Type eventSourceType,
  278.       EventHandler<TEventArgs> eventHandler) =>
  279.       TryRemoveObserver(eventName, eventSourceType, (Delegate) eventHandler);
  280.  
  281.     /// <inheritdoc />
  282.     public bool TryRemoveGlobalObserver(string eventName, Delegate eventHandler)
  283.     {
  284.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  285.  
  286.       string fullyQualifiedEventIdOfGlobalSource =
  287.         CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  288.       this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  289.       return this.EventHandlerTable.TryRemove(fullyQualifiedEventIdOfGlobalSource, out _);
  290.     }
  291.  
  292.     /// <inheritdoc />
  293.     public bool TryRemoveGlobalObserver<TEventArgs>(string eventName, EventHandler<TEventArgs> eventHandler)
  294.     {
  295.       Type normalizedEventHandlerType = NormalizeEventHandlerType< TEventArgs>(eventHandler.GetType());
  296.  
  297.       string fullyQualifiedEventIdOfGlobalSource =
  298.         CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  299.       this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  300.       return this.EventHandlerTable.TryRemove(fullyQualifiedEventIdOfGlobalSource, out _);
  301.     }
  302.  
  303.     /// <inheritdoc />
  304.     public bool TryRemoveGlobalObserver(Delegate eventHandler)
  305.     {
  306.       Type normalizedEventHandlerType = NormalizeEventHandlerType(eventHandler.GetType());
  307.       return TryRemoveGlobalObserverInternal(normalizedEventHandlerType);
  308.     }
  309.  
  310.     /// <inheritdoc />
  311.     public bool TryRemoveGlobalObserver<TEventArgs>(EventHandler<TEventArgs> eventHandler)
  312.     {
  313.       Type normalizedEventHandlerType = NormalizeEventHandlerType< TEventArgs>(eventHandler.GetType());
  314.       return TryRemoveGlobalObserverInternal(normalizedEventHandlerType);
  315.     }
  316.  
  317.     /// <inheritdoc />
  318.     public bool TryRemoveAllObservers(string eventName, Type eventSourceType)
  319.     {
  320.       string fullyQualifiedEventIdOfSpecificSource =
  321.         CreateFullyQualifiedEventIdOfSpecificSource(eventSourceType, eventName);
  322.       if (this.EventHandlerTable.TryRemove(fullyQualifiedEventIdOfSpecificSource,
  323.         out List<Delegate> removedDelegates))
  324.       {
  325.         foreach (Delegate eventHandler in removedDelegates)
  326.         {
  327.           this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  328.         }
  329.         return true;
  330.       }
  331.       return false;
  332.     }
  333.  
  334.     /// <inheritdoc />
  335.     public bool TryRemoveAllObservers(Type eventSourceType)
  336.     {
  337.       bool result = false;
  338.       string fullyQualifiedEventIdOfSpecificSourcePrefix =
  339.         CreateFullyQualifiedEventIdOfSpecificSource(eventSourceType, string.Empty);
  340.       for (var index = this.EventHandlerTable.Count - 1; index >= 0; index--)
  341.       {
  342.         KeyValuePair<string, List<Delegate>> handlersEntry = this.EventHandlerTable.ElementAt(index);
  343.         if (handlersEntry.Key.StartsWith(fullyQualifiedEventIdOfSpecificSourcePrefix, StringComparison.Ordinal))
  344.         {
  345.           result |= this.EventHandlerTable.TryRemove(handlersEntry.Key, out _);
  346.           foreach (Delegate eventHandler in handlersEntry.Value)
  347.           {
  348.             this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  349.           }
  350.         }
  351.       }
  352.  
  353.       return result;
  354.     }
  355.  
  356.     /// <inheritdoc />
  357.     public bool TryRemoveAllObservers(string eventName)
  358.     {
  359.       bool result = false;
  360.       string fullyQualifiedEventIdSuffix = $".{eventName}";
  361.       for (var index = this.EventHandlerTable.Count - 1; index >= 0; index--)
  362.       {
  363.         KeyValuePair<string, List<Delegate>> handlersEntry = this.EventHandlerTable.ElementAt(index);
  364.         if (handlersEntry.Key.EndsWith(fullyQualifiedEventIdSuffix, StringComparison.Ordinal))
  365.         {
  366.           result |= this.EventHandlerTable.TryRemove(handlersEntry.Key, out List<Delegate> _);
  367.           foreach (Delegate eventHandler in handlersEntry.Value)
  368.           {
  369.             this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  370.           }
  371.         }
  372.       }
  373.  
  374.       return result;
  375.     }
  376.  
  377.     #endregion Implementation of IEventAggregator
  378.  
  379.     private bool TryRegisterObserverInternal(
  380.       Delegate eventHandler,
  381.       string fullyQualifiedEventName)
  382.     {
  383.       if (this.EventHandlerTable.TryGetValue(fullyQualifiedEventName, out List<Delegate> handlers))
  384.       {
  385.         handlers.Add(eventHandler);
  386.         return true;
  387.       }
  388.  
  389.       return this.EventHandlerTable.TryAdd(fullyQualifiedEventName, new List<Delegate>() { eventHandler });
  390.     }
  391.  
  392.     private bool TryRegisterObserverInternal(
  393.       Delegate eventHandler,
  394.       string fullyQualifiedEventName,
  395.       SynchronizationContext synchronizationContext)
  396.     {
  397.       this.EventHandlerSynchronizationContextTable.TryAdd(eventHandler, synchronizationContext);
  398.       if (this.EventHandlerTable.TryGetValue(fullyQualifiedEventName, out List<Delegate> handlers))
  399.       {
  400.         handlers.Add(eventHandler);
  401.         return true;
  402.       }
  403.  
  404.       return this.EventHandlerTable.TryAdd(fullyQualifiedEventName, new List<Delegate>() { eventHandler });
  405.     }
  406.  
  407.     private bool TryRemoveGlobalObserverInternal(Type normalizedEventHandlerType)
  408.     {
  409.       bool result = false;
  410.       string fullyQualifiedEventIdOfGlobalSourcePrefix =
  411.         CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  412.       for (var index = this.EventHandlerTable.Count - 1; index >= 0; index--)
  413.       {
  414.         KeyValuePair<string, List<Delegate>> handlersEntry = this.EventHandlerTable.ElementAt(index);
  415.         if (handlersEntry.Key.StartsWith(fullyQualifiedEventIdOfGlobalSourcePrefix, StringComparison.Ordinal))
  416.         {
  417.           result |= this.EventHandlerTable.TryRemove(handlersEntry.Key, out List<Delegate> _);
  418.           foreach (Delegate eventHandler in handlersEntry.Value)
  419.           {
  420.             this.EventHandlerSynchronizationContextTable.TryRemove(eventHandler, out _);
  421.           }
  422.         }
  423.       }
  424.  
  425.       return result;
  426.     }
  427.  
  428.     private void DelegateHandleEvent((Type EventHandlerType, ICollection<string> EventIds) eventInfo, object sender, object args)
  429.     {
  430.       IEnumerable<Delegate> handlers = eventInfo.EventIds
  431.         .SelectMany(
  432.           eventId => this.EventHandlerTable.TryGetValue(eventId, out List<Delegate> delegates)
  433.             ? delegates
  434.             : new List<Delegate>());
  435.  
  436.       foreach (Delegate handler in handlers)
  437.       {
  438.         try
  439.         {
  440.           if (this.EventHandlerSynchronizationContextTable.TryGetValue(handler, out SynchronizationContext synchronizationContext))
  441.           {
  442.             synchronizationContext.Post(new SendOrPostCallback(param => handler.DynamicInvoke(sender, args)), null);
  443.           }
  444.           else
  445.           {
  446.             handler.DynamicInvoke(sender, args);
  447.           }
  448.         }
  449.         catch (ArgumentException e)
  450.         {
  451.           MethodInfo delegateInvokeMethodInfo = handler.GetType().GetMethod("Invoke");
  452.           string handlerSignatureParameterList = delegateInvokeMethodInfo?
  453.             .GetParameters()
  454.             .Select(parameterInfo => parameterInfo.ParameterType.FullName)
  455.             .Aggregate((result, current) => result += ", " + current).TrimEnd(',', ' ');
  456.  
  457.           throw new WrongEventHandlerSignatureException(
  458.             $"The found callback signature does not match the registered delegate{Environment.NewLine}'{FormatTypeName(handler.GetType())}'. {Environment.NewLine}{Environment.NewLine}Expected: '{delegateInvokeMethodInfo.ReturnType.Name} {handler.Method.Name}({handlerSignatureParameterList})'.{Environment.NewLine}Actual: '{handler.Method}'.", e);
  459.         }
  460.       }
  461.     }
  462.  
  463.     private string FormatTypeName(Type typeToFormat, bool isFullyQualified = true)
  464.     {
  465.       if (!typeToFormat.IsGenericType)
  466.       {
  467.         return isFullyQualified ? typeToFormat.FullName : typeToFormat.Name;
  468.       }
  469.       Type[] genericArguments = typeToFormat.GetGenericArguments();
  470.       string originalTypeName = isFullyQualified ? typeToFormat.FullName : typeToFormat.Name;
  471.       return originalTypeName.Substring(0, originalTypeName.IndexOf("`", StringComparison.OrdinalIgnoreCase)) + "<" + String.Join(", ", genericArguments.Select(type => FormatTypeName(type))) + ">";
  472.     }
  473.  
  474.     private bool TryCreateEventIdOfInterfaceType(object eventSource, string eventName, out string eventId)
  475.     {
  476.       eventId = string.Empty;
  477.  
  478.       Type eventSourceInterfaceType = eventSource.GetType().GetInterfaces().FirstOrDefault(
  479.         interfaceType => interfaceType.GetEvent(
  480.           eventName,
  481.           BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance |
  482.           BindingFlags.Static) != null);
  483.  
  484.       if (eventSourceInterfaceType != null)
  485.       {
  486.         var fullyQualifiedInterfaceEventIdOfSpecificEvent =
  487.           CreateFullyQualifiedEventIdOfSpecificSource(eventSourceInterfaceType, eventName);
  488.         eventId = fullyQualifiedInterfaceEventIdOfSpecificEvent;
  489.       }
  490.  
  491.       return !string.IsNullOrWhiteSpace(eventId);
  492.     }
  493.  
  494.     private List<string> CreateEventIdsOfConcreteType(
  495.       object eventSource,
  496.       Type normalizedEventHandlerType,
  497.       string eventName)
  498.     {
  499.       var fullyQualifiedEventIdOfGlobalEvent =
  500.         CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, eventName);
  501.       var fullyQualifiedEventIdOfUnknownGlobalEvent =
  502.         CreateFullyQualifiedEventIdOfGlobalSource(normalizedEventHandlerType, string.Empty);
  503.       var fullyQualifiedImplementationEventIdOfSpecificEvent =
  504.         CreateFullyQualifiedEventIdOfSpecificSource(eventSource.GetType(), eventName);
  505.  
  506.       var eventIds = new List<string>
  507.       {
  508.         fullyQualifiedImplementationEventIdOfSpecificEvent, fullyQualifiedEventIdOfGlobalEvent,
  509.         fullyQualifiedEventIdOfUnknownGlobalEvent
  510.       };
  511.       return eventIds;
  512.     }
  513.  
  514.     private Type NormalizeEventHandlerType(Type eventHandlerType) =>
  515.       eventHandlerType == typeof(EventHandler) || eventHandlerType == typeof(Action<object, EventArgs>)
  516.         ? typeof(EventHandler<EventArgs>)
  517.         : eventHandlerType;
  518.  
  519.     private Type NormalizeEventHandlerType<TEventArgs>(Type eventHandlerType) =>
  520.       eventHandlerType == typeof(EventHandler) || eventHandlerType == typeof(Action<object, EventArgs>)
  521.         ? typeof(EventHandler<EventArgs>)
  522.         : eventHandlerType == typeof(EventHandler<TEventArgs>)
  523.           ? typeof(EventHandler<TEventArgs>)
  524.           : eventHandlerType;
  525.  
  526.     private string CreateFullyQualifiedEventIdOfGlobalSource(Type eventHandlerType, string eventName) => eventHandlerType.FullName.ToLowerInvariant() + "." + eventName;
  527.  
  528.     private string CreateFullyQualifiedEventIdOfSpecificSource(Type eventSource, string eventName) => eventSource.AssemblyQualifiedName.ToLowerInvariant() + "." + eventSource.FullName.ToLowerInvariant() + "." + eventName;
  529.  
  530.     private ConcurrentDictionary<string, List<Delegate>> EventHandlerTable { get; }
  531.     private ConcurrentDictionary<Delegate, SynchronizationContext> EventHandlerSynchronizationContextTable { get; }
  532.     private ConditionalWeakTable<object, List<(EventInfo EventInfo, Delegate Handler)>> EventPublisherTable { get; }
  533.   }
  534. }
Add Comment
Please, Sign In to add comment