public void OnType(TypeDefinition type)
{
if(type.IsInterface)
return;
foreach(var method in type.Methods)
{
try
{
string fieldName;
MethodReference methodR;
#region Get required info or continue
if(method.Name.StartsWith("add_")) {
fieldName = method.Name.Substring("add_".Length);
methodR = combineR;
} else if(method.Name.StartsWith("remove_")) {
fieldName = method.Name.Substring("remove_".Length);
methodR = removeR;
} else {
continue;
}
#endregion
var newI = new List<Instruction>();
var processor = method.Body.GetILProcessor();
bool foundCompExch = false;
foreach(var existingInstruction in processor.Body.Instructions) {
if(existingInstruction.OpCode == OpCodes.Call) {
var meth = existingInstruction.Operand as MethodReference;
if(meth != null) {
if(meth.Name == "CompareExchange") {
if(Verbosity > 7)
Console.WriteLine(" Found CompareExchange");
foundCompExch = true;
break;
}
}
}
}
if(!foundCompExch) {
if(Verbosity >= Verbosities.SkippingVerbose) {
Console.WriteLine(" . ignoring body with no CompareExchange: " + type.Name + "." + method.Name);
}
skipped++;
continue;
}
FieldReference field;
if(type.HasGenericParameters)
{
var giType = new GenericInstanceType(type);
// var
// string x = type.FullName;
//giType.
field = type.Fields.Where(f => f.Name == fieldName).FirstOrDefault();
Console.WriteLine("==== GENERICTYPE: " + type + " (" + type.GenericParameters.Count + ") " + giType.ToString() + ", Field: " + field.FullName);
foreach(var genPar in type.GenericParameters)
{
Console.WriteLine(" ==> " + genPar.FullName);
}
}
else
{
field = type.Fields.Where(f => f.Name == fieldName).FirstOrDefault();
}
if(field == null)
throw new Exception("Could not find field: " + fieldName + " in type " + type.FullName);
// IL_0000: ldarg.0
newI.Add(processor.Create(OpCodes.Ldarg_0));
// IL_0001: ldarg.0
newI.Add(processor.Create(OpCodes.Ldarg_0));
// IL_0002: ldfld class MyNamespace.ActionBool MyNamespace.EnableableBase::myHandler
newI.Add(processor.Create(OpCodes.Ldfld, field));
// IL_0007: ldarg.1
newI.Add(processor.Create(OpCodes.Ldarg_1));
// IL_0008: call class [mscorlib]System.Delegate class [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
newI.Add(processor.Create(OpCodes.Call, methodR));
// IL_000d: castclass MyNamespace.ActionBool
newI.Add(processor.Create(OpCodes.Castclass, field.FieldType));
// IL_0012: stfld class MyNamespace.ActionBool MyNamespace.EnableableBase::myHandler
newI.Add(processor.Create(OpCodes.Stfld, field));
// IL_0017: ret
newI.Add(processor.Create(OpCodes.Ret));
#region Replace the instructions
replaced++;
processor.Body.Instructions.Clear();
foreach(var i in newI) {
processor.Body.Instructions.Add(i);
}
if(Verbosity >= Verbosities.Success) {
Console.WriteLine(" - replaced method: " + type.Name + "." + method.Name);
}
#endregion
} catch(Exception ex) {
Console.WriteLine("Exception for method: " + type.FullName + "." + method.Name + ": " + ex);
}
}
}