博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# WeakEvent
阅读量:5132 次
发布时间:2019-06-13

本文共 8968 字,大约阅读时间需要 29 分钟。

using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Reflection.Emit;using System.Runtime.CompilerServices;using System.Text;namespace Rocky{    internal delegate bool Forwarder(WeakReference weakRef, object sender, EventArgs e);    ///     /// The forwarder-generating code is in a separate class because it does not depend on type T.    ///     internal static class WeakEventForwarderProvider    {        private static MethodInfo getTarget;        private static Type[] forwarderParameters;        private static Hashtable forwarders;        static WeakEventForwarderProvider()        {            getTarget = typeof(WeakReference).GetMethod("get_Target");            forwarderParameters = new Type[] { typeof(WeakReference), typeof(object), typeof(EventArgs) };            forwarders = Hashtable.Synchronized(new Hashtable());        }        internal static Forwarder GetForwarder(MethodInfo method)        {            var fd = (Forwarder)forwarders[method];            if (fd != null)            {                return fd;            }            if (method.DeclaringType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Length != 0)            {                throw new ArgumentException("Cannot create weak event to anonymous method with closure.");            }            ParameterInfo[] parameters = method.GetParameters();            DynamicMethod dm = new DynamicMethod("WeakEvent", typeof(bool), forwarderParameters, method.DeclaringType);            ILGenerator il = dm.GetILGenerator();            if (!method.IsStatic)            {                il.Emit(OpCodes.Ldarg_0);                il.EmitCall(OpCodes.Callvirt, getTarget, null);                il.Emit(OpCodes.Dup);                Label label = il.DefineLabel();                il.Emit(OpCodes.Brtrue, label);                il.Emit(OpCodes.Pop);                il.Emit(OpCodes.Ldc_I4_1);                il.Emit(OpCodes.Ret);                il.MarkLabel(label);                // The castclass here is required for the generated code to be verifiable.                // We can leave it out because we know this cast will always succeed                // (the instance/method pair was taken from a delegate).                // Unverifiable code is fine because private reflection is only allowed under FullTrust                // anyways.                //il.Emit(OpCodes.Castclass, method.DeclaringType);            }            il.Emit(OpCodes.Ldarg_1);            il.Emit(OpCodes.Ldarg_2);            // This castclass here is required to prevent creating a hole in the .NET type system.            // See Program.TypeSafetyProblem in the 'SmartWeakEventBenchmark' to see the effect when            // this cast is not used.            // You can remove this cast if you trust add FastSmartWeakEvent.Raise callers to do            // the right thing, but the small performance increase (about 5%) usually isn't worth the risk.            il.Emit(OpCodes.Castclass, parameters[1].ParameterType);            il.EmitCall(OpCodes.Call, method, null);            il.Emit(OpCodes.Ldc_I4_0);            il.Emit(OpCodes.Ret);            forwarders[method] = fd = (Forwarder)dm.CreateDelegate(typeof(Forwarder));            return fd;        }        internal static void OverForwarder(MethodInfo method)        {            forwarders.Remove(method);        }    }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Collections.Specialized;using System.Reflection;using System.Reflection.Emit;namespace Rocky{    public sealed class WeakEvent
where T : class { #region NestedTypes private struct EventEntry { public readonly Forwarder Forwarder; public readonly MethodInfo TargetMethod; public readonly WeakReference TargetReference; public EventEntry(Forwarder forwarder, MethodInfo targetMethod, WeakReference targetReference) { this.Forwarder = forwarder; this.TargetMethod = targetMethod; this.TargetReference = targetReference; } } #endregion #region Static static WeakEvent() { Type type = typeof(T); if (!type.IsSubclassOf(typeof(Delegate))) { throw new ArgumentException("T must be a delegate type"); } MethodInfo invoke = type.GetMethod("Invoke"); if (invoke == null || invoke.GetParameters().Length != 2) { throw new ArgumentException("T must be a delegate type taking 2 parameters"); } ParameterInfo senderParameter = invoke.GetParameters()[0]; if (senderParameter.ParameterType != typeof(object)) { throw new ArgumentException("The first delegate parameter must be of type 'object'"); } ParameterInfo argsParameter = invoke.GetParameters()[1]; if (!(typeof(EventArgs).IsAssignableFrom(argsParameter.ParameterType))) { throw new ArgumentException("The second delegate parameter must be derived from type 'EventArgs'"); } if (invoke.ReturnType != typeof(void)) { throw new ArgumentException("The delegate return type must be void."); } } #endregion private List
eventEntries; private object SyncRoot { get { return eventEntries; } } public WeakEvent() { eventEntries = new List
(); } private void RemoveEntry(int index, MethodInfo method) { lock (SyncRoot) { eventEntries.RemoveAt(index); } WeakEventForwarderProvider.OverForwarder(method); } private void RemoveDeadEntries() { lock (SyncRoot) { eventEntries.RemoveAll(entry => { if (entry.TargetReference != null && !entry.TargetReference.IsAlive) { WeakEventForwarderProvider.OverForwarder(entry.TargetMethod); return true; } return false; }); } } public void Add(T e) { if (e == null) { return; } Delegate d = (Delegate)(object)e; if (eventEntries.Count == eventEntries.Capacity) { RemoveDeadEntries(); } MethodInfo targetMethod = d.Method; object targetInstance = d.Target; WeakReference target = targetInstance != null ? new WeakReference(targetInstance) : null; lock (SyncRoot) { eventEntries.Add(new EventEntry(WeakEventForwarderProvider.GetForwarder(targetMethod), targetMethod, target)); } } public void Remove(T e) { if (e == null) { return; } Delegate d = (Delegate)(object)e; object targetInstance = d.Target; MethodInfo targetMethod = d.Method; lock (SyncRoot) { for (int i = eventEntries.Count - 1; i >= 0; i--) { EventEntry entry = eventEntries[i]; if (entry.TargetReference != null) { object target = entry.TargetReference.Target; if (target == null) { RemoveEntry(i, entry.TargetMethod); } else if (target == targetInstance && entry.TargetMethod == targetMethod) { RemoveEntry(i, entry.TargetMethod); break; } } else { if (targetInstance == null && entry.TargetMethod == targetMethod) { RemoveEntry(i, entry.TargetMethod); break; } } } } } public bool Raise() { return Raise(this, EventArgs.Empty); } public bool Raise(object sender, EventArgs e) { bool needClear = false; foreach (EventEntry entry in eventEntries) { needClear |= entry.Forwarder(entry.TargetReference, sender, e); } if (needClear) { RemoveDeadEntries(); } return eventEntries.Count > 0; } }}

 

转载于:https://www.cnblogs.com/Googler/archive/2013/03/29/2988603.html

你可能感兴趣的文章
SNF快速开发平台MVC-EasyQuery-拖拽生成SQL脚本
查看>>
DrawerLayout实现双向侧滑
查看>>
MySQL入门很简单-触发器
查看>>
LVM快照(snapshot)备份
查看>>
绝望的第四周作业
查看>>
一月流水账
查看>>
数论四大定理
查看>>
npm 常用指令
查看>>
20几个正则常用正则表达式
查看>>
TextArea中定位光标位置
查看>>
非常棒的Visual Studo调试插件:OzCode 2.0 下载地址
查看>>
判断字符串在字符串中
查看>>
hdu4374One hundred layer (DP+单调队列)
查看>>
类间关系总结
查看>>
properties配置文件读写,追加
查看>>
Linux环境下MySql安装和常见问题的解决
查看>>
lrzsz——一款好用的文件互传工具
查看>>
ZPL语言完成条形码的打印
查看>>
这20件事千万不要对自己做!
查看>>
Linux环境下Redis安装和常见问题的解决
查看>>