我也想这样做,我想出了一个很酷的方法来做一些类似皇帝 XLII 的想法。但是它不使用表达式树,正如前面提到的,这不能完成,因为表达式树不允许使用+=
or -=
。
然而,我们可以使用一个巧妙的技巧,使用 .NET 远程代理(或任何其他代理,如 LinFu 或 Castle DP)来拦截对生命周期很短的代理对象上的添加/删除处理程序的调用。这个代理对象的作用就是简单的在它上面调用一些方法,并允许它的方法调用被拦截,此时我们可以找出事件的名称。
这听起来很奇怪,但这里是代码(顺便说一句,只有在你有MarshalByRefObject
代理对象的接口或接口时才有效)
假设我们有以下接口和类
public interface ISomeClassWithEvent {
event EventHandler<EventArgs> Changed;
}
public class SomeClassWithEvent : ISomeClassWithEvent {
public event EventHandler<EventArgs> Changed;
protected virtual void OnChanged(EventArgs e) {
if (Changed != null)
Changed(this, e);
}
}
然后我们可以有一个非常简单的类,它期望一个Action<T>
委托将传递给T
.
这是代码
public class EventWatcher<T> {
public void WatchEvent(Action<T> eventToWatch) {
CustomProxy<T> proxy = new CustomProxy<T>(InvocationType.Event);
T tester = (T) proxy.GetTransparentProxy();
eventToWatch(tester);
Console.WriteLine(string.Format("Event to watch = {0}", proxy.Invocations.First()));
}
}
诀窍是将代理对象传递给Action<T>
提供的委托。
在我们有以下CustomProxy<T>
代码的地方,谁拦截了+=
对-=
代理对象的调用
public enum InvocationType { Event }
public class CustomProxy<T> : RealProxy {
private List<string> invocations = new List<string>();
private InvocationType invocationType;
public CustomProxy(InvocationType invocationType) : base(typeof(T)) {
this.invocations = new List<string>();
this.invocationType = invocationType;
}
public List<string> Invocations {
get {
return invocations;
}
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
[DebuggerStepThrough]
public override IMessage Invoke(IMessage msg) {
String methodName = (String) msg.Properties["__MethodName"];
Type[] parameterTypes = (Type[]) msg.Properties["__MethodSignature"];
MethodBase method = typeof(T).GetMethod(methodName, parameterTypes);
switch (invocationType) {
case InvocationType.Event:
invocations.Add(ReplaceAddRemovePrefixes(method.Name));
break;
// You could deal with other cases here if needed
}
IMethodCallMessage message = msg as IMethodCallMessage;
Object response = null;
ReturnMessage responseMessage = new ReturnMessage(response, null, 0, null, message);
return responseMessage;
}
private string ReplaceAddRemovePrefixes(string method) {
if (method.Contains("add_"))
return method.Replace("add_","");
if (method.Contains("remove_"))
return method.Replace("remove_","");
return method;
}
}
然后我们剩下的就是按如下方式使用它
class Program {
static void Main(string[] args) {
EventWatcher<ISomeClassWithEvent> eventWatcher = new EventWatcher<ISomeClassWithEvent>();
eventWatcher.WatchEvent(x => x.Changed += null);
eventWatcher.WatchEvent(x => x.Changed -= null);
Console.ReadLine();
}
}
这样做我会看到这个输出:
Event to watch = Changed
Event to watch = Changed