Skip to content

Instantly share code, notes, and snippets.

@mayuki
Created March 18, 2009 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mayuki/81125 to your computer and use it in GitHub Desktop.
Save mayuki/81125 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Remoting;
using System.Reflection;
using System.Security.Policy;
using System.Xml.Serialization;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
namespace ConsoleApplication1
{
public class A : MarshalByRefObject
{
public event EventHandler HandleEvent;
public void FireEvent()
{
if (HandleEvent != null)
HandleEvent(this, EventArgs.Empty);
}
public void Handler(Object sender, EventArgs e)
{
Console.WriteLine("inside A");
}
}
public class EventMangedProxy<T> : RealProxy where T : MarshalByRefObject
{
private static readonly Dictionary<MethodInfo, EventInfo> EventsByAddMethods = new Dictionary<MethodInfo, EventInfo>();
private static readonly Dictionary<MethodInfo, EventInfo> EventsByRemoveMethods = new Dictionary<MethodInfo, EventInfo>();
private T _targetObject;
private Dictionary<EventInfo, List<Delegate>> _eventHandlers = new Dictionary<EventInfo, List<Delegate>>();
static EventMangedProxy()
{
foreach (var ev in typeof(T).GetEvents())
{
EventsByAddMethods.Add(ev.GetAddMethod(), ev);
EventsByRemoveMethods.Add(ev.GetRemoveMethod(), ev);
}
}
public EventMangedProxy(T aObj)
: base(typeof(T))
{
_targetObject = aObj;
}
public void RemoveAllEvents()
{
foreach (var evHandlers in _eventHandlers)
{
EventInfo evInfo = evHandlers.Key;
foreach (var evHandler in evHandlers.Value)
evInfo.RemoveEventHandler(_targetObject, evHandler);
}
}
public override IMessage Invoke(IMessage msg)
{
IMethodMessage methodMessage = msg as IMethodMessage;
MethodInfo methodInfo = (MethodInfo)methodMessage.MethodBase;
if (EventsByAddMethods.ContainsKey(methodInfo))
{
EventInfo eventInfo = EventsByAddMethods[methodInfo];
if (!_eventHandlers.ContainsKey(eventInfo))
_eventHandlers[eventInfo] = new List<Delegate>();
_eventHandlers[eventInfo].Add((Delegate)methodMessage.Args[0]);
}
else if (EventsByRemoveMethods.ContainsKey(methodInfo))
{
EventInfo eventInfo = EventsByRemoveMethods[methodInfo];
if (_eventHandlers.ContainsKey(eventInfo))
_eventHandlers[eventInfo].Remove((Delegate)methodMessage.Args[0]);
}
return RemotingServices.ExecuteMessage(_targetObject, (IMethodCallMessage)msg);
}
}
public class Program : MarshalByRefObject
{
static void Main(string[] args)
{
A aObjOrig = new A();
EventMangedProxy<A> evProxy = new EventMangedProxy<A>(aObjOrig);
A aObj = (A)evProxy.GetTransparentProxy();
// 直接削除されないイベントを追加
aObjOrig.HandleEvent += aObjOrig.Handler;
aObjOrig.HandleEvent += (sender, e) => { Console.WriteLine("Maumau"); };
// プロクシ経由で削除されるイベントを追加
aObj.HandleEvent += aObj.Handler;
aObj.HandleEvent += (sender, e) => { Console.WriteLine("Hauhau"); };
// イベントを実行 (4つ結果が出るはず[inside A, Maumau, inside A, Hauhau])
aObj.FireEvent();
// プロクシ経由で追加したイベントを削除
evProxy.RemoveAllEvents();
// イベントを追加
aObj.HandleEvent += (sender, e) => { Console.WriteLine("Gaogao"); };
// イベントを実行 (3つになるはず[inside A, Maumau, Gaogao])
aObj.FireEvent();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment