public void Prepare(MutableType mutableType, EventInfo eventInfo) { var eventType = eventInfo.EventHandlerType; var eventInvoke = eventType.GetMethod("Invoke"); var original = Expression.Field( new ThisExpression(mutableType), mutableType.GetField(eventInfo.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)); var broker = Expression.Field( new ThisExpression(mutableType), mutableType.AddField(eventInfo.Name + "Broker", eventType)); var addMethod = mutableType.GetOrAddMutableMethod(eventInfo.GetAddMethod(true)); var removeMethod = mutableType.GetOrAddMutableMethod(eventInfo.GetRemoveMethod(true)); var parameters = eventInvoke.GetParameters().Select(ParameterDeclaration.CreateEquivalent); var invokeMethod = mutableType.AddMethod( "invoke_" + eventInfo.Name, MethodAttributes.Private, eventInvoke.ReturnType, parameters, ctx => Expression.Call(broker, eventInvoke, ctx.Parameters.Cast <Expression>())); var invokeDelegate = new NewDelegateExpression(eventType, new ThisExpression(mutableType.UnderlyingSystemType), invokeMethod); addMethod.SetBody( ctx => Expression.Block( Expression.IfThen( Expression.Equal(broker, Expression.Constant(null, eventType)), Expression.Call(ctx.This, new NonVirtualCallMethodInfoAdapter(addMethod.UnderlyingSystemMethodInfo), invokeDelegate)), Expression.Assign( broker, Expression.Convert(Expression.Call(null, s_combineMethod, new Expression[] { broker, ctx.Parameters.Single() }), eventType)))); removeMethod.SetBody( ctx => Expression.Block( Expression.IfThen( Expression.Equal(broker, Expression.Constant(null, eventType)), Expression.Call(ctx.This, new NonVirtualCallMethodInfoAdapter(addMethod.UnderlyingSystemMethodInfo), invokeDelegate)), Expression.Assign( broker, Expression.Convert(Expression.Call(null, s_combineMethod, new Expression[] { broker, ctx.Parameters.Single() }), eventType)))); }