пост Aviad является хорошим началом. Вы можете использовать его для событий типа EventHandler
. Для других типов делегатов вы можете использовать один и тот же метод, создающий обработчик для каждого типа вручную.
Если вы хотите быть более гибким, вы должны создать обработчик событий во время выполнения, используя System.Reflection.Emit
. Вот подробное объяснение: http://msdn.microsoft.com/en-us/library/ms228976.aspx. Прокрутите вниз до «Чтобы создать обработчик события во время выполнения с использованием динамического метода».
// EDIT
Я создал простой класс, который способен обрабатывать все события конкретного объекта и передать их универсального обработчика событий. Код основан на примерах от Microsoft и XTreme.NET Talk.
Основная идея
- создать метод во время выполнения, который имеет те же аргументы, что события
- набор это mehod в качестве обработчика события для каждого события в Type.GetEvents()
- из этого вызова метода универсальный обработчик события
Использование
Объект для прикрепления к передается в конструкторе. Следующий анонимный метод типа UniversalEventHandler
используется для обработки всех событий. Этот метод получает имя события как eventName
и аргументы события в args
. Вы можете установить точку останова на этом методе и просмотреть аргументы в Visual Studio или распечатать их самостоятельно.В этом примере используется только имя события, которое можно найти в окне «Вывод» (меню «Вид»> «Вывод» в Visual Studio). В этом примере рассматривается стандартная кнопка button1
.
private void Form1_Load(object sender, EventArgs e)
{
UniversalEventHandler handler = (UniversalEventHandler) delegate(string eventName, object[] args)
{
System.Diagnostics.Trace.WriteLine(eventName);
};
EventInspector inspector = new EventInspector(button1, handler);
}
Код
public delegate void UniversalEventHandler(string eventName, object[] args);
public class EventInspector
{
private UniversalEventHandler eventHandler;
private object srcObject;
public EventInspector(object srcObject, UniversalEventHandler eventHandler)
{
this.eventHandler = eventHandler;
this.srcObject = srcObject;
Attach();
}
public void EventReceived(string eventName, object[] args)
{
if (eventHandler != null)
eventHandler(eventName, args);
}
public void Attach()
{
Type type = srcObject.GetType();
EventInfo[] srcEvents = type.GetEvents();
for (int i = 0; i < srcEvents.Length; i++)
{
EventInfo srcEvent = srcEvents[i];
Type[] parameterTypes = GetDelegateParams(srcEvent.EventHandlerType);
DynamicMethod handler = new DynamicMethod("", typeof(void), parameterTypes, typeof(EventInspector));
string name = srcEvent.Name;
ILGenerator il = handler.GetILGenerator();
il.DeclareLocal(typeof(object[]));
il.DeclareLocal(typeof(string));
il.Emit(OpCodes.Ldstr, srcEvent.Name);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldc_I4, parameterTypes.Length - 1);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Stloc_0);
for (int j = 0; j < parameterTypes.Length - 1; j++)
{
Type parameter = parameterTypes[j];
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldc_I4, j);
il.Emit(OpCodes.Ldarg, j + 1);
il.Emit(OpCodes.Stelem_Ref);
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldloc_1);
il.Emit(OpCodes.Ldloc_0);
MethodInfo eventReceivedMethod = this.GetType().GetMethod("EventReceived", BindingFlags.Public | BindingFlags.Instance);
il.EmitCall(OpCodes.Callvirt, eventReceivedMethod, null);
il.Emit(System.Reflection.Emit.OpCodes.Ret);
srcEvent.AddEventHandler(srcObject, handler.CreateDelegate(srcEvent.EventHandlerType, this));
}
}
private Type[] GetDelegateParams(Type d)
{
MethodInfo delegateMethod = d.GetMethod("Invoke");
ParameterInfo[] delegateParams = delegateMethod.GetParameters();
Type[] result = new Type[delegateParams.Length + 1];
result[0] = this.GetType();
for (int i = 0; i < delegateParams.Length; i++)
{
result[i + 1] = delegateParams[i].ParameterType;
}
return result;
}
}
@Petr: Прежде всего, метод Aviad, к сожалению, не работает для меня (.NET 2), так как он не может преобразовать «System.EventHandler» в «System.Windows.Forms.MouseEventHandler». Вторичный, мне не нужно * генерировать * событие, но * перехватывать * его ... – serhio
Удивительный класс !! Разумеется, полезно в миллионах сценариев. – Dested
Serhio: Используя код в моем отредактированном ответе, вы можете перехватить все события и его аргументы. метод Aviad работает для меня под .NET 2.0, пожалуйста, попробуйте этот код: this.GetType() GetEvent ("KeyDown") AddEventHandler (это, (EventHandler) делегат (объект ЦСИ EventArgs эв) { ... .. }); Он ничего не сделает, потому что KeyDown не является EventHandler, но он будет компилироваться без ошибок. Если вы измените «KeyDown» на обработчик «Click», будет запущен. Надеюсь, это поможет. –