Guest User

WeakEvent

a guest
Jul 31st, 2015
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.93 KB | None | 0 0
  1. /== основное ======================================================================================/
  2. /== нагло позаимствовано и доработано напильником =================================================/
  3. /== http://www.thomaslevesque.com/2010/05/17/c-a-simple-implementation-of-the-weakevent-pattern/ ==/
  4.  
  5. public class WeakDelegate<T> : IEquatable<T>
  6. {
  7.     private WeakReference mTargetReference;
  8.     private MethodInfo mMethod;
  9.  
  10.     public WeakDelegate(Delegate RealDelegate)
  11.     {
  12.         if (RealDelegate.Target != null)
  13.         {
  14.             mTargetReference = new WeakReference(RealDelegate.Target);
  15.         }
  16.         else
  17.         {
  18.             mTargetReference = null;
  19.         }
  20.         mMethod = RealDelegate.Method;
  21.     }
  22.  
  23.     public bool IsAlive
  24.     {
  25.         get
  26.         {
  27.             return ((mTargetReference == null) || (mTargetReference.IsAlive));
  28.         }
  29.     }
  30.  
  31.     internal void Invoke(params object[] Args)
  32.     {
  33.         if (mTargetReference != null)
  34.         {
  35.             mMethod.Invoke(mTargetReference.Target, Args);
  36.         }
  37.     }
  38.  
  39.     #region Члены IEquatable<T>
  40.     public bool Equals(T OtherEventHandler)
  41.     {
  42.         if (!IsAlive) return false;
  43.  
  44.         Delegate D = (Delegate)((object)OtherEventHandler);
  45.         if (D == null) return false;
  46.  
  47.         if (mTargetReference.Target != D.Target) return false;
  48.         if (!mMethod.Equals(D.Method)) return false;
  49.  
  50.         return true;
  51.     }
  52.     #endregion
  53.  
  54.     public override string ToString()
  55.     {
  56.         string T = "Target = " + (mTargetReference.IsAlive ? mTargetReference.Target.ToString() : "is null.");
  57.         return T + " " + mMethod.ToString();
  58.     }
  59. }
  60.  
  61. public class WeakEvent<TEventHandler>
  62. {
  63.     private List<WeakDelegate<TEventHandler>> mHandlers;
  64.  
  65.     public WeakEvent()
  66.     {
  67.         mHandlers = new List<WeakDelegate<TEventHandler>>();
  68.     }
  69.  
  70.     public virtual void AddHandler(TEventHandler Handler)
  71.     {
  72.         Delegate D = (Delegate)(object)Handler;
  73.         mHandlers.Add(new WeakDelegate<TEventHandler>(D));
  74.  
  75.         RemoveDeadHandlers();
  76.     }
  77.  
  78.     public virtual void RemoveHandler(TEventHandler Handler)
  79.     {
  80.         RemoveEqualsHandlers(Handler);
  81.         RemoveDeadHandlers();
  82.  
  83.         // сдохни ебаная лямда
  84.         //mHandlers.RemoveAll(wd => !wd.IsAlive || wd.Equals(Handler));
  85.     }
  86.  
  87.     private void RemoveEqualsHandlers(TEventHandler Handler)
  88.     {
  89.         EqualsHandlersPredicate<TEventHandler> P = new EqualsHandlersPredicate<TEventHandler>(Handler);
  90.         mHandlers.RemoveAll(P.Predicate);
  91.     }
  92.     private void RemoveDeadHandlers()
  93.     {
  94.         NotAliveHandlersPredicate<TEventHandler> P = new NotAliveHandlersPredicate<TEventHandler>();
  95.         mHandlers.RemoveAll(P.Predicate);
  96.     }
  97.  
  98.     public virtual void Raise(params object[] Args)
  99.     {
  100.         // удолить ??
  101.         var Handlers = mHandlers.ToArray();
  102.  
  103.         foreach (var WeakDelegate in Handlers)
  104.         {
  105.             if (WeakDelegate.IsAlive)
  106.             {
  107.                 WeakDelegate.Invoke(Args);
  108.             }
  109.             else
  110.             {
  111.                 // удолить ??
  112.                 mHandlers.Remove(WeakDelegate);
  113.             }
  114.         }
  115.     }
  116.  
  117.     // временно для теста
  118.     public List<WeakDelegate<TEventHandler>> Handlers
  119.     {
  120.         get { return mHandlers; }
  121.     }
  122. }
  123.  
  124. public class NotAliveHandlersPredicate<TEventHandler>
  125. {
  126.     public bool Predicate(WeakDelegate<TEventHandler> OtherWeakDelegate)
  127.     {
  128.         return (!OtherWeakDelegate.IsAlive);
  129.     }
  130. }
  131. public class EqualsHandlersPredicate<TEventHandler>
  132. {
  133.     public TEventHandler Handler;
  134.     public EqualsHandlersPredicate(TEventHandler Handler)
  135.     {
  136.         this.Handler = Handler;
  137.     }
  138.     public bool Predicate(WeakDelegate<TEventHandler> OtherWeakDelegate)
  139.     {
  140.         return OtherWeakDelegate.Equals(Handler);
  141.     }
  142. }
  143.  
  144. /== тест =======================================================================/
  145. public class EventSourceW
  146. {
  147.     private WeakEvent<Action<string>> mHandlersOnEmitString = new WeakEvent<Action<string>>();
  148.     public event Action<string> OnEmitString
  149.     {
  150.         add { mHandlersOnEmitString.AddHandler(value); }
  151.         remove { mHandlersOnEmitString.RemoveHandler(value); }
  152.     }
  153.     public void RaiseOnEmitString(string S)
  154.     {
  155.         Console.WriteLine("Raise OnEmitString with " + S);
  156.         mHandlersOnEmitString.Raise(S);
  157.     }
  158.  
  159.     private WeakEvent<Action<int>> mHandlersOnEmitInt = new WeakEvent<Action<int>>();
  160.     public event Action<int> OnEmitInt
  161.     {
  162.         add { mHandlersOnEmitInt.AddHandler(value); }
  163.         remove { mHandlersOnEmitInt.RemoveHandler(value); }
  164.     }
  165.     public void RaiseOnEmitInt(int I)
  166.     {
  167.         Console.WriteLine("Raise OnEmitInt with " + I.ToString());
  168.         mHandlersOnEmitInt.Raise(I);
  169.     }
  170.  
  171.     public void PrintHandlersList()
  172.     {
  173.         Console.WriteLine();
  174.         Console.WriteLine("Handlers OnEmitInt:");
  175.         for (int i = 0; i < mHandlersOnEmitInt.Handlers.Count; i++)
  176.         {
  177.             Console.WriteLine(mHandlersOnEmitInt.Handlers[i].ToString());    
  178.         }
  179.  
  180.         Console.WriteLine();
  181.         Console.WriteLine("Handlers OnEmitString:");
  182.         for (int i = 0; i < mHandlersOnEmitString.Handlers.Count; i++)
  183.         {
  184.             Console.WriteLine(mHandlersOnEmitString.Handlers[i].ToString());
  185.         }
  186.  
  187.         Console.WriteLine();
  188.     }
  189. }
  190.  
  191. public class EventLisnerW
  192. {
  193.     public void SubscribeOnEvent(EventSourceW ES)
  194.     {
  195.         Console.WriteLine("Listner subscribe...");
  196.  
  197.         ES.OnEmitInt += GetInt;
  198.         ES.OnEmitString += GetString;
  199.     }
  200.  
  201.     public void UnSubscribeOnEvent(EventSource ES)
  202.     {
  203.         Console.WriteLine("Listner unsubscribe...");
  204.        
  205.         ES.OnEmitInt -= GetInt;
  206.         ES.OnEmitString -= GetString;
  207.     }
  208.  
  209.     public void GetInt(int I)
  210.     {
  211.         Console.WriteLine("GetInt = " + I.ToString());
  212.     }
  213.     public void GetString(string S)
  214.     {
  215.         Console.WriteLine("GetString = " + S);
  216.     }
  217. }
  218.  
  219. public static class TestWeakEventsW
  220. {
  221.     private static EventSourceW mS;
  222.     private static EventLisnerW mL;
  223.     private static long mStartMemUse = 0;
  224.  
  225.     public static void MainTest()
  226.     {
  227.         Console.WriteLine("GC.MaxGeneration = " + GC.MaxGeneration.ToString());
  228.  
  229.         mStartMemUse = GC.GetTotalMemory(true);
  230.         Console.WriteLine("GC.GetTotalMemory = " + mStartMemUse.ToString());
  231.  
  232.         mS = new EventSourceW();
  233.  
  234.         for (int i = 0; i < 10000; i++)
  235.         {
  236.             Console.WriteLine();
  237.             Console.WriteLine("New Listner {0}...", (i + 1));
  238.             mL = new EventLisnerW();
  239.             mL.SubscribeOnEvent(mS);
  240.  
  241.             mS.RaiseOnEmitInt(RandomInt());
  242.             mS.RaiseOnEmitInt(RandomInt());
  243.  
  244.             Console.WriteLine("GC.Collect...");
  245.             GC.Collect();
  246.  
  247.             mS.RaiseOnEmitInt(RandomInt());
  248.             mS.RaiseOnEmitInt(RandomInt());
  249.  
  250.             Console.WriteLine("Listner == null.");
  251.             mL = null;
  252.  
  253.             Console.WriteLine("GC.Collect...");
  254.             GC.Collect();
  255.  
  256.             mS.RaiseOnEmitInt(RandomInt());
  257.             mS.RaiseOnEmitInt(RandomInt());
  258.  
  259.             if ((i % 5) == 0)
  260.             {
  261.                 mS.RaiseOnEmitString("Test OnEmitString for 6 iteration...");
  262.             }
  263.  
  264.             mS.RaiseOnEmitInt(RandomInt());
  265.             mS.RaiseOnEmitInt(RandomInt());
  266.  
  267.             mS.PrintHandlersList();
  268.  
  269.             Console.WriteLine("GC.GetTotalMemory = " + (GC.GetTotalMemory(true)).ToString());
  270.  
  271.             //Console.ReadKey();
  272.         }
  273.  
  274.         Console.WriteLine("Start mem = {0}", mStartMemUse);
  275.         Console.WriteLine();
  276.         Console.WriteLine("Happy End...");
  277.     }
  278.    
  279.     private static Random mRandom = new Random();
  280.     private static int RandomInt()
  281.     {
  282.         return mRandom.Next(100);
  283.     }
  284. }
Advertisement
Add Comment
Please, Sign In to add comment