Thanks for the quick response ... I am sure it is something silly that I
have missed.
Given class:
public class ClassWithClonedMethod
{
public void GenericMethod<T>()
{
//return default(T);
}
public void CallToGenericMethod<T>()
{
GenericMethod<T>();
}
}
And test(NOT):
[Test]
public void should_emit_call_to_generic_properly()
{
var assembly =
AssemblyDefinition.ReadAssembly("TestAssembly.dll");
var type = assembly.MainModule.Types.Where(t => t.Name ==
"ClassWithClonedMethod").First();
var renamedMethod = type.Methods.Where(m => m.Name ==
"GenericMethod").First();
// Create new method
var methodThatShouldReplaceOriginal = new
MethodDefinition(renamedMethod.Name, renamedMethod.Attributes,
renamedMethod.ReturnType);
renamedMethod.DeclaringType.Methods.Add(methodThatShouldReplaceOriginal);
// Rename existing method
renamedMethod.Name = string.Format("{0}_Clone",
renamedMethod.Name);
// Copy vars and stuff
methodThatShouldReplaceOriginal.CallingConvention =
renamedMethod.CallingConvention;
methodThatShouldReplaceOriginal.SemanticsAttributes =
renamedMethod.SemanticsAttributes;
renamedMethod.CustomAttributes.ToList().ForEach(a =>
methodThatShouldReplaceOriginal.CustomAttributes.Add(a));
renamedMethod.SecurityDeclarations.ToList().ForEach(s =>
methodThatShouldReplaceOriginal.SecurityDeclarations.Add(s));
methodThatShouldReplaceOriginal.IsAbstract =
renamedMethod.IsAbstract;
methodThatShouldReplaceOriginal.IsAddOn = renamedMethod.IsAddOn;
methodThatShouldReplaceOriginal.IsAssembly =
renamedMethod.IsAssembly;
methodThatShouldReplaceOriginal.IsCheckAccessOnOverride =
renamedMethod.IsCheckAccessOnOverride;
methodThatShouldReplaceOriginal.IsCompilerControlled =
renamedMethod.IsCompilerControlled;
methodThatShouldReplaceOriginal.IsFamily =
renamedMethod.IsFamily;
methodThatShouldReplaceOriginal.IsFamilyAndAssembly =
renamedMethod.IsFamilyAndAssembly;
methodThatShouldReplaceOriginal.IsFamilyOrAssembly =
renamedMethod.IsFamilyOrAssembly;
methodThatShouldReplaceOriginal.IsFinal = renamedMethod.IsFinal;
methodThatShouldReplaceOriginal.IsFire = renamedMethod.IsFire;
methodThatShouldReplaceOriginal.IsForwardRef =
renamedMethod.IsForwardRef;
methodThatShouldReplaceOriginal.IsGetter =
renamedMethod.IsGetter;
methodThatShouldReplaceOriginal.IsHideBySig =
renamedMethod.IsHideBySig;
methodThatShouldReplaceOriginal.IsIL = renamedMethod.IsIL;
methodThatShouldReplaceOriginal.IsInternalCall =
renamedMethod.IsInternalCall;
methodThatShouldReplaceOriginal.IsManaged =
renamedMethod.IsManaged;
methodThatShouldReplaceOriginal.IsNative =
renamedMethod.IsNative;
methodThatShouldReplaceOriginal.IsNewSlot =
renamedMethod.IsNewSlot;
methodThatShouldReplaceOriginal.IsPInvokeImpl =
renamedMethod.IsPInvokeImpl;
methodThatShouldReplaceOriginal.IsPreserveSig =
renamedMethod.IsPreserveSig;
methodThatShouldReplaceOriginal.IsPrivate =
renamedMethod.IsPrivate;
methodThatShouldReplaceOriginal.IsPublic =
renamedMethod.IsPublic;
methodThatShouldReplaceOriginal.IsRemoveOn =
renamedMethod.IsRemoveOn;
methodThatShouldReplaceOriginal.IsReuseSlot =
renamedMethod.IsReuseSlot;
methodThatShouldReplaceOriginal.IsRuntime =
renamedMethod.IsRuntime;
methodThatShouldReplaceOriginal.IsRuntimeSpecialName =
renamedMethod.IsRuntimeSpecialName;
methodThatShouldReplaceOriginal.IsSetter =
renamedMethod.IsSetter;
methodThatShouldReplaceOriginal.IsSpecialName =
renamedMethod.IsSpecialName;
methodThatShouldReplaceOriginal.IsStatic =
renamedMethod.IsStatic;
methodThatShouldReplaceOriginal.IsSynchronized =
renamedMethod.IsSynchronized;
methodThatShouldReplaceOriginal.IsUnmanaged =
renamedMethod.IsUnmanaged;
methodThatShouldReplaceOriginal.IsUnmanagedExport =
renamedMethod.IsUnmanagedExport;
methodThatShouldReplaceOriginal.IsVirtual =
renamedMethod.IsVirtual;
methodThatShouldReplaceOriginal.NoInlining =
renamedMethod.NoInlining;
methodThatShouldReplaceOriginal.NoOptimization =
renamedMethod.NoOptimization;
// Copy parameters across
if (renamedMethod.HasParameters)
foreach (var parameter in renamedMethod.Parameters.ToList())
methodThatShouldReplaceOriginal.Parameters.Add(parameter);
// Copy generic parameters across
if (renamedMethod.HasGenericParameters)
{
foreach (var genericParameter in
renamedMethod.GenericParameters.ToList())
{
if (genericParameter != null)
{
var newGenericParameter = new
GenericParameter(genericParameter.Name, methodThatShouldReplaceOriginal);
methodThatShouldReplaceOriginal.GenericParameters.Add(newGenericParameter);
newGenericParameter.Attributes =
genericParameter.Attributes;
genericParameter.Constraints.ForEach(gp =>
newGenericParameter.Constraints.Add(gp));
genericParameter.CustomAttributes.ForEach(ca =>
newGenericParameter.CustomAttributes.Add(ca));
newGenericParameter.DeclaringType =
genericParameter.DeclaringType;
genericParameter.GenericParameters.ForEach(gp =>
newGenericParameter.GenericParameters.Add(gp));
newGenericParameter.HasDefaultConstructorConstraint
= genericParameter.HasDefaultConstructorConstraint;
newGenericParameter.IsContravariant =
genericParameter.IsContravariant;
newGenericParameter.IsCovariant =
genericParameter.IsCovariant;
newGenericParameter.IsNonVariant =
genericParameter.IsNonVariant;
}
}
}
// Get IL processor and emit call to renamed clone
var il = methodThatShouldReplaceOriginal.Body.GetILProcessor();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, renamedMethod);
il.Emit(OpCodes.Ret);
assembly.Write("Foo.dll");
}
Yields:
.method public hidebysig instance void GenericMethod<T>() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void
CryoAOP.TestAssembly.TypeThatShouldBeIntercepted::GenericMethod_Clone<*[1]*
>()
IL_0006: ret
} // end of method TypeThatShouldBeIntercepted::GenericMethod
Where I am expecting:
.method public hidebysig instance void GenericMethod<T>() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void
CryoAOP.TestAssembly.TypeThatShouldBeIntercepted::GenericMethod_Clone<*!!0*
>()
IL_0006: ret
} // end of method TypeThatShouldBeIntercepted::GenericMethod
What do you guys think?
On 21 February 2011 13:59, Raph <[email protected]> wrote:
> to me it looks like you are missing the genericarguments.
>
> but as jb said, posting your code would help ;)
>
> --
> --
> mono-cecil
--
--
mono-cecil