Hi Alex Dude, you are a legend! That worked ... :)
Thanks ~G On 21 February 2011 20:11, Alex Corrado <[email protected]> wrote: > 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
