I might be wrong, but I think you are trying to call the unspecialized
generic method directly. You need to instantiate it with type
arguments. Instead of calling renamedMethod directly, add the
extension method somewhere, and try something like:
il.Emit(OpCodes.Call, renamedMethod.MakeGeneric
(methodThatShouldReplaceOriginal.GenericParameters.ToArray ()));
public static MethodReference MakeGeneric (this MethodReference
method, params TypeReference [] args)
{
if (args.Length == 0)
return method;
if (method.GenericParameters.Count != args.Length)
throw new ArgumentException ("Invalid number of
generic type
arguments supplied");
var genericTypeRef = new GenericInstanceMethod (method);
foreach (var arg in args)
genericTypeRef.GenericArguments.Add (arg);
return genericTypeRef;
}
Hope this helps!
-Alex
On Mon, Feb 21, 2011 at 11:28 AM, Gavin van der Merwe
<[email protected]> wrote:
> 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
--
--
mono-cecil