Created
April 28, 2012 21:12
-
-
Save einarwh/2522052 to your computer and use it in GitHub Desktop.
Code to inject notification calls, optionally refactoring out original setter.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void InjectNotification(MethodDefinition methodDef, | |
IEnumerable<string> propNames) | |
{ | |
if (_notifyMethodDef == null || methodDef == null) | |
{ | |
return; | |
} | |
if (HasMultipleReturnPoints(methodDef)) | |
{ | |
RefactorSetterAndInjectNotification(methodDef, propNames); | |
} | |
else | |
{ | |
InjectNotificationDirectly(methodDef, propNames); | |
} | |
} | |
private bool HasMultipleReturnPoints(MethodDefinition methodDef) | |
{ | |
return methodDef.Body.Instructions.Count( | |
insn => insn.OpCode == OpCodes.Ret) > 1; | |
} | |
private void RefactorSetterAndInjectNotification( | |
MethodDefinition oldMethodDef, | |
IEnumerable<string> propNames) | |
{ | |
var methodName = "Refactored" + oldMethodDef.Name | |
.Substring(PropertySetterPrefix.Length) + "Setter"; | |
var methodDef = new MethodDefinition(methodName, | |
oldMethodDef.Attributes, | |
oldMethodDef.ReturnType); | |
foreach (var oldParamDef in oldMethodDef.Parameters) | |
{ | |
var paramDef = new ParameterDefinition( | |
oldParamDef.Name, | |
oldParamDef.Attributes, | |
oldParamDef.ParameterType); | |
methodDef.Parameters.Add(paramDef); | |
} | |
methodDef.Body = oldMethodDef.Body; | |
_typeDef.Methods.Add(methodDef); | |
oldMethodDef.Body = new MethodBody(oldMethodDef); | |
var il = oldMethodDef.Body.GetILProcessor(); | |
Action<OpCode> op = x => il.Append(il.Create(x)); | |
op(OpCodes.Ldarg_0); | |
op(OpCodes.Ldarg_1); | |
il.Append(il.Create(OpCodes.Call, methodDef)); | |
op(OpCodes.Ret); | |
InjectNotificationDirectly(oldMethodDef, propNames); | |
} | |
private void InjectNotificationDirectly(MethodDefinition methodDef, | |
IEnumerable<string> propNames) | |
{ | |
var il = methodDef.Body.GetILProcessor(); | |
var returnInsn = il.Body.Instructions.Last(); | |
foreach (var s in propNames) | |
{ | |
var loadThis = il.Create(OpCodes.Ldarg_0); | |
var loadString = il.Create(OpCodes.Ldstr, s); | |
var callMethod = il.Create(OpCodes.Call, _notifyMethodDef); | |
il.InsertBefore(returnInsn, loadThis); | |
il.InsertBefore(returnInsn, loadString); | |
il.InsertBefore(returnInsn, callMethod); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment