Using VS2005, I dynamically create an event delegate. Code follows question.
My method gets the event's parameters and passes them onto a common event handler. My delegate gets called when expected and in turn, calls my common event handler. However, once in the common event handler code, the "this pointer" is wrong and hence I can't access other class properties and methods.
Even if I invoke the dynamic method directly, the "this pointer" is stuffed.
Any ideas on what I'm doing wrong (or invalid assumptions I'm making)?
Thanks for any help.
void EventHandler::CreateDynamicEventHandler()
{
System::Type ^ eventClass = m_eventSource->GetTarget()->GetType();
// Get event info and the type of delegate.
array<System::Type^>^ args;
EventInfo ^ eventInfo = eventClass->GetEvent(m_eventName);
System::Type ^ tDelegate = eventInfo->EventHandlerType;
MethodInfo^ invoke = tDelegate->GetMethod( "Invoke" );
// The generated delegate will call a standard method (CommonEventHandler)
// Get the method info for that method.
array<System::Type^>^ commonArgs = {System::String::typeid, array<System::Object^>::typeid};
MethodInfo ^ methodInfo = EventHandler::typeid->GetMethod("CommonEventHandler", commonArgs);
// Create dynamic method
array<System::Type^> ^ paramTypes = GetDelegateParameterTypes(tDelegate);
DynamicMethod ^ dynamicMethod = gcnew DynamicMethod("Dyna",
nullptr,
paramTypes,
::EventHandler::typeid);
// Generate method body
ILGenerator ^ ilGen = dynamicMethod->GetILGenerator();
// Create a local variable 'args'
int paramCount = paramTypes->Length;
LocalBuilder ^ localObj = ilGen->DeclareLocal(array<System::Object^>::typeid);
// create object array of proper length
ilGen->Emit(OpCodes::Ldc_I4, paramCount);
ilGen->Emit(OpCodes::Newarr, System::Object::typeid);
ilGen->Emit(OpCodes::Stloc_0);
// Now put all arguments in the object array
for (System::Int32 i= 0; i<paramCount; i++)
{
System::Byte b = System::Convert::ToByte(i);
ilGen->Emit(OpCodes::Ldloc_0); // Local variable - the array
ilGen->Emit(OpCodes::Ldc_I4, i); // Index into array
ilGen->Emit(OpCodes::Ldarg_S, b); // Value to save is in bth argument to this method
if (paramTypes[i]->IsValueType)
ilGen->Emit(OpCodes::Box, paramTypes[i]); // Box value types
ilGen->Emit(OpCodes::Stelem_Ref, i);
}
ilGen->Emit(OpCodes::Ldarg_0); // 'this' ptr (required for instance calls)
ilGen->Emit(OpCodes::Ldstr, m_eventName); // Just to help with debugging!
ilGen->Emit(OpCodes::Ldloc_0);
ilGen->EmitCall(OpCodes::Call, methodInfo, nullptr);
ilGen->Emit(OpCodes::Ret);
// Create delegate (Also completes dynamic method build)
System::Delegate ^ del = dynamicMethod->CreateDelegate(tDelegate);
// Add delegate to event's invocation list
MethodInfo ^ addHandler = eventInfo->GetAddMethod();
array<System::Object^> ^ addHandlerArgs = {del};
addHandler->Invoke(m_eventSource->GetTarget(), addHandlerArgs);
}