Good day! My purpose is to implement class which will allow us subscribe and unsubscribe objects to(from) events. Here is the code of my class.
public static class EventSubscriber
{
public static void AddEventHandler(EventInfo eventInfo, object item, Action action)
{
var parameters = GetParameters(eventInfo);
var handler = GetHandler(eventInfo, action, parameters);
eventInfo.AddEventHandler(item, handler);
}
public static void RemoveEventHandler(EventInfo eventInfo,
object item, Action action)
{
var parameters = GetParameters(eventInfo);
var handler = GetHandler(eventInfo, action, parameters);
eventInfo.RemoveEventHandler(item, handler);
}
private static ParameterExpression[] GetParameters(EventInfo eventInfo)
{
return eventInfo.EventHandlerType
.GetMethod("Invoke")
.GetParameters()
.Select(parameter => Expression.Parameter(parameter.ParameterType))
.ToArray();
}
private static Delegate GetHandler(EventInfo eventInfo,
Action action, ParameterExpression[] parameters)
{
return Expression.Lambda(
eventInfo.EventHandlerType,
Expression.Call(Expression.Constant(action),
"Invoke", Type.EmptyTypes), parameters)
.Compile();
}
}
As you can see here are 2 public methods which actually subscribe and unsubscribe objects to(from) event. And here is the sample how I test it
class Program
{
static void Main()
{
Test test = new Test();
test.SubscribeTimer();
while (true)
{
if(test.a == 10)
{
break;
}
}
test.UnsubscribeTimer();
while (true)
{
}
}
}
class Test
{
System.Timers.Timer timer;
public int a = 0;
public Test()
{
timer = new System.Timers.Timer(1000);
timer.Start();
}
public void SubscribeTimer()
{
var eventInfo = typeof(System.Timers.Timer).GetEvent("Elapsed");
EventSubscriber.AddEventHandler(eventInfo, timer, TimerElapsed);
EventSubscriber.RemoveEventHandler(eventInfo, timer, TimerNotElapsed);
}
public void UnsubscribeTimer()
{
var eventInfo = typeof(System.Timers.Timer).GetEvent("Elapsed");
EventSubscriber.AddEventHandler(eventInfo, timer, TimerNotElapsed);
EventSubscriber.RemoveEventHandler(eventInfo, timer, TimerElapsed);
}
public void TimerElapsed()
{
Console.WriteLine("timer elapsed");
a++;
}
public void TimerNotElapsed()
{
Console.WriteLine("timer not elapsed");
a++;
}
}
The expected behaviour of sample is that on the begining we will see the message "timer elapsed" every second, after 10-th second we should see only "timer not elapsed" and we do, but we still see "timer elapsed" too. This means that AddEventHandler
method works, but RemoveEventHandler
methods doesn't.
I would be very happy if you will help me. Thanks in advance.
Aucun commentaire:
Enregistrer un commentaire