protected T CreateDelegate() { var parameters = new List <Type> (); parameters.Add(this.GetType()); parameters.AddRange(this.Method.GetParameters().Select(p => p.ParameterType)); var method = new DynamicMethod("WeakDelegateDynamic", this.Method.ReturnType, parameters.ToArray(), this.GetType(), true); var hasReturnType = (this.Method.ReturnType != typeof(void)); if (this.Method.IsGenericMethod) { method.MakeGenericMethod(this.Method.GetGenericArguments()); } var il = method.GetILGenerator(); // IL Code should be equivalent of... /* * var target = this.Reference.Target; * if (!CheckDelegate()) * return; * * return this.Method(args); * */ // Create our labels var returnLabel = il.DefineLabel(); var callLabel = il.DefineLabel(); // Define our local variables il.DeclareLocal(typeof(object)); il.DeclareLocal(hasReturnType ? this.Method.ReturnType : typeof(int)); il.DeclareLocal(typeof(bool)); // Load the target value on to the stack to keep it alive il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, GetReferenceMethod); il.Emit(OpCodes.Callvirt, WeakReferenceGetTargetMethod); il.Emit(OpCodes.Stloc_0); // Call CheckDelegate il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, CheckDelegateMethod); il.Emit(OpCodes.Stloc_2); // If it did not return true then return immediately il.Emit(OpCodes.Ldloc_2); il.Emit(OpCodes.Brtrue_S, callLabel); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Br_S, returnLabel); // Load our target and all of our arguments il.MarkLabel(callLabel); il.Emit(OpCodes.Ldloc_0); for (int i = 0; i < this.Method.GetParameters().Length; i++) { il.Emit(OpCodes.Ldarg, i + 1); } // Call our method and return il.Emit(this.Method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, this.Method); if (hasReturnType) { il.Emit(OpCodes.Stloc_1); } il.Emit(OpCodes.Br_S, returnLabel); il.MarkLabel(returnLabel); if (hasReturnType) { il.Emit(OpCodes.Ldloc_1); } il.Emit(OpCodes.Ret); return(method.CreateDelegate(this.Type, this) as T); }