MethodDefinition InjectInterceptedMethod(TypeDefinition targetType, MethodDefinition innerOnPropertyChanged)
{
delegateHolderInjector.Execute(targetType, innerOnPropertyChanged);
var method = new MethodDefinition(eventInvokerNameResolver.EventInvokerNames.First(), GetMethodAttributes(targetType), msCoreReferenceFinder.VoidTypeReference);
var propertyName = new ParameterDefinition("propertyName", ParameterAttributes.None, msCoreReferenceFinder.StringTypeReference);
method.Parameters.Add(propertyName);
if (interceptorFinder.IsBeforeAfter)
{
var before = new ParameterDefinition("before", ParameterAttributes.None, msCoreReferenceFinder.ObjectTypeReference);
method.Parameters.Add(before);
var after = new ParameterDefinition("after", ParameterAttributes.None, msCoreReferenceFinder.ObjectTypeReference);
method.Parameters.Add(after);
}
var action = new VariableDefinition("firePropertyChanged", msCoreReferenceFinder.ActionTypeReference);
method.Body.Variables.Add(action);
var variableDefinition = new VariableDefinition("delegateHolder", delegateHolderInjector.TypeDefinition);
method.Body.Variables.Add(variableDefinition);
var instructions = method.Body.Instructions;
var last = Instruction.Create(OpCodes.Ret);
instructions.Add(Instruction.Create(OpCodes.Newobj, delegateHolderInjector.ConstructorDefinition));
instructions.Add(Instruction.Create(OpCodes.Stloc_1));
instructions.Add(Instruction.Create(OpCodes.Ldloc_1));
instructions.Add(Instruction.Create(OpCodes.Ldarg_1));
instructions.Add(Instruction.Create(OpCodes.Stfld, delegateHolderInjector.PropertyName));
instructions.Add(Instruction.Create(OpCodes.Ldloc_1));
instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
instructions.Add(Instruction.Create(OpCodes.Stfld, delegateHolderInjector.Target));
instructions.Add(Instruction.Create(OpCodes.Ldloc_1));
instructions.Add(Instruction.Create(OpCodes.Ldftn, delegateHolderInjector.MethodDefinition));
instructions.Add(Instruction.Create(OpCodes.Newobj, msCoreReferenceFinder.ActionConstructorReference));
instructions.Add(Instruction.Create(OpCodes.Stloc_0));
instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
instructions.Add(Instruction.Create(OpCodes.Ldloc_0));
instructions.Add(Instruction.Create(OpCodes.Ldloc_1));
instructions.Add(Instruction.Create(OpCodes.Ldfld, delegateHolderInjector.PropertyName));
if (interceptorFinder.IsBeforeAfter)
{
instructions.Add(Instruction.Create(OpCodes.Ldarg_2));
instructions.Add(Instruction.Create(OpCodes.Ldarg_3));
instructions.Add(Instruction.Create(OpCodes.Call, interceptorFinder.InterceptMethod));
}
else
{
instructions.Add(Instruction.Create(OpCodes.Call, interceptorFinder.InterceptMethod));
}
instructions.Add(last);
method.Body.InitLocals = true;
targetType.Methods.Add(method);
return method;
}