private MethodDefinition EnsureOnPropertyChangedMethod()
{
var type = _catelType.TypeDefinition;
MethodDefinition methodDefinition = null;
var possibleMethods = type.Methods.Where(definition => definition.Name == "OnPropertyChanged" && definition.HasParameters).ToList();
foreach (var possibleMethod in possibleMethods)
{
if (string.Equals(possibleMethod.Parameters[0].ParameterType.FullName, _catelType.AdvancedPropertyChangedEventArgsType.FullName))
{
methodDefinition = possibleMethod;
break;
}
}
var baseOnPropertyChangedInvoker = _catelType.BaseOnPropertyChangedInvoker;
if (methodDefinition == null)
{
var voidType = _msCoreReferenceFinder.GetCoreTypeReference("Void");
methodDefinition = new MethodDefinition("OnPropertyChanged", MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual, type.Module.Import(voidType));
methodDefinition.Parameters.Add(new ParameterDefinition("e", ParameterAttributes.None, _catelType.AdvancedPropertyChangedEventArgsType));
var body = methodDefinition.Body;
body.SimplifyMacros();
body.Instructions.Add(Instruction.Create(OpCodes.Nop));
body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_1));
body.Instructions.Add(Instruction.Create(OpCodes.Call, baseOnPropertyChangedInvoker));
body.Instructions.Add(Instruction.Create(OpCodes.Nop));
body.Instructions.Add(Instruction.Create(OpCodes.Ret));
body.OptimizeMacros();
type.Methods.Add(methodDefinition);
methodDefinition.MarkAsCompilerGenerated(_msCoreReferenceFinder);
}
else
{
// Note: need to replace call to base, otherwise it might skip a call to a just generated base member
var body = methodDefinition.Body;
var hasReplaced = false;
body.SimplifyMacros();
foreach (var instruction in body.Instructions)
{
if (instruction.OpCode == OpCodes.Call)
{
var methodReference = instruction.Operand as MethodReference;
if ((methodReference != null) && string.Equals(methodReference.Name, baseOnPropertyChangedInvoker.Name))
{
instruction.Operand = baseOnPropertyChangedInvoker;
hasReplaced = true;
}
}
}
body.OptimizeMacros();
if (!methodDefinition.IsMarkedAsGeneratedCode())
{
// Don't support this, see CTL-569
return null;
}
}
return methodDefinition;
}
#endregion