Advertisement
Guest User

DynamicEventHandler for C# Metro Apps / WinRT / Universal

a guest
Aug 9th, 2015
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.23 KB | None | 0 0
  1. using System;
  2. using System.Reflection;
  3. using System.Linq;
  4. using Singularity.Core;
  5.  
  6. #if NETFX_CORE
  7.  
  8. using Windows.UI.Xaml;
  9. using System.Runtime.InteropServices.WindowsRuntime;
  10.  
  11. #else
  12.  
  13. using System.Windows;
  14. using System.Windows.Markup;
  15.  
  16. #endif
  17.  
  18. /// <summary>
  19. /// By: Caino MDK
  20. /// </summary>
  21. namespace Singularity.Core
  22. {
  23.     public sealed class DynamicEventHandler : DisposableBase
  24.     {
  25.         private EventInfo eventInfo;
  26.         private Delegate handler;
  27.  
  28. #if NETFX_CORE
  29.         private Action<EventRegistrationToken> remove;
  30. #endif
  31.  
  32.         public string EventName { get; private set; }
  33.  
  34.         public object AssociatedObject { get; private set; }
  35.  
  36.         public Action<object, object> EventHandler { get; private set; }
  37.  
  38.         public DynamicEventHandler(object associatedObject, string eventName, Action<object, object> eventHandler)
  39.         {
  40.             this.EventName = eventName;
  41.             this.AssociatedObject = associatedObject;
  42.             this.EventHandler = eventHandler;
  43.  
  44.             this.AttachEvent();
  45.         }
  46.  
  47.         private void AttachEvent()
  48.         {
  49.             this.eventInfo = this.AssociatedObject.GetType().GetRuntimeEvent(this.EventName);
  50.  
  51.             if (eventInfo == null)
  52.                 return;
  53.  
  54. #if NETFX_CORE
  55.  
  56.             var addMethodInfo = eventInfo.AddMethod;
  57.             var removeMethodInfo = eventInfo.RemoveMethod;
  58.  
  59.             var eventHandlerType = addMethodInfo.GetParameters()[0].ParameterType;
  60.  
  61.             this.remove = x => removeMethodInfo.Invoke(this.AssociatedObject, new object[] { x });
  62.  
  63.             var method = this.GetType().GetRuntimeMethods().First(x => x.Name == "ExecuteCommand");
  64.             this.handler = method.CreateDelegate(eventInfo.EventHandlerType, this);
  65.  
  66.             WindowsRuntimeMarshal.AddEventHandler(x => this.AddEventHandler(addMethodInfo, x), remove, this.handler);
  67. #else
  68.             var method = this.GetType().GetRuntimeMethods().First(x => x.Name == "ExecuteCommand");
  69.             this.handler = method.CreateDelegate(eventInfo.EventHandlerType, this);
  70.             this.eventInfo.AddEventHandler(this.AssociatedObject, this.handler);
  71.  
  72. #endif
  73.         }
  74.  
  75. #if NETFX_CORE
  76.  
  77.         private EventRegistrationToken AddEventHandler(MethodInfo addMethodInfo, Delegate method)
  78.         {
  79.             var token = addMethodInfo.Invoke(this.AssociatedObject, new object[] { method });
  80.  
  81.             // in some conditions (I never found out why) the "get" of the event does not return a
  82.             // EventRegistrationToken. In this case we have to use our workaround
  83.             // If someone has an idea why this is happening... please notify me
  84.             if (token == null)
  85.             {
  86.                 var eventTokenTable = this.AssociatedObject.GetType().GetTypeInfo().GetDeclaredField("_" + this.EventName);
  87.  
  88.                 // maybe the tokentable is named camelcase
  89.                 if (eventTokenTable == null)
  90.                 {
  91.                     eventTokenTable = this.AssociatedObject.GetType().GetTypeInfo().GetDeclaredField(this.EventName.ToCamelCase());
  92.                 }
  93.  
  94.                 // still no table? maybe camelcased with underscore
  95.                 if (eventTokenTable == null)
  96.                 {
  97.                     eventTokenTable = this.AssociatedObject.GetType().GetTypeInfo().GetDeclaredField("_" + this.EventName.ToCamelCase());
  98.                 }
  99.  
  100.                 // still no table? fuck this... I don't know
  101.                 if (eventTokenTable == null)
  102.                     throw new Exception("No token for event found");
  103.  
  104.                 var eventTokenTableInstance = eventTokenTable.GetValue(this.AssociatedObject);
  105.                 var getTokenMethod = eventTokenTableInstance.GetType().GetTypeInfo().GetDeclaredMethod("GetToken");
  106.                 token = getTokenMethod.Invoke(eventTokenTableInstance, new object[] { method });
  107.             }
  108.  
  109.             return (EventRegistrationToken)token;
  110.         }
  111.  
  112. #endif
  113.  
  114.         private void DetachEvent()
  115.         {
  116. #if NETFX_CORE
  117.             if (this.remove == null || this.handler == null)
  118.                 return;
  119.  
  120.             WindowsRuntimeMarshal.RemoveEventHandler(this.remove, this.handler);
  121.  
  122. #else
  123.             if (this.eventInfo == null || this.handler == null)
  124.                 return;
  125.  
  126.             this.eventInfo.RemoveEventHandler(this.AssociatedObject, this.handler);
  127. #endif
  128.             this.eventInfo = null;
  129.             this.handler = null;
  130.         }
  131.  
  132.         protected override void OnDispose(bool disposeManaged)
  133.         {
  134.             if (disposeManaged)
  135.             {
  136.                 this.DetachEvent();
  137.                 this.AssociatedObject = null;
  138.                 this.EventHandler = null;
  139.             }
  140.         }
  141.  
  142.         private void ExecuteCommand(object sender, object args)
  143.         {
  144.             if (this.EventHandler != null)
  145.             {
  146.                 this.EventHandler(sender, args);
  147.             }
  148.  
  149. #if NETFX_CORE
  150.             var handledProperty = args.GetType().GetRuntimeProperty("Handled");
  151. #else
  152.             var handledProperty = args.GetType().GetProperty("Handled");
  153. #endif
  154.             if (handledProperty != null)
  155.             {
  156.                 handledProperty.SetValue(args, true);
  157.             }
  158.         }
  159.     }
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement