[Mono-list] Embedded API: Method signature not found with generic parameter

mugginsoft jonathan at mugginsoft.com
Mon Jul 15 21:08:42 UTC 2013


Just to give the completed test code:

// Obj-C
- (MonoObject *)execute
{
    // get a reference to the System.Core assembly
    MonoAssemblyName *monoAssemblyName =
mono_assembly_name_new("System.Core");
    MonoAssembly *monoSystemCoreAssembly =
mono_assembly_loaded(monoAssemblyName);
    mono_assembly_name_free(monoAssemblyName);
    MonoType *monoType =
mono_reflection_type_from_name("System.Linq.Enumerable", (MonoImage
*)mono_assembly_get_image(monoSystemCoreAssembly));
    MonoClass *monoClass = mono_class_from_mono_type(monoType);
    if (!monoClass) abort;

    
    //[DBMonoObjectRepresentation logMonoClassInfo:monoClass];
    
    // ToList is an extension method defined as a static method on
System.Linq.Enumerable
    // mono_class_get_method_from_name takes a simple method name
    const char *methodName = "ToList";
    MonoMethod *tempGenericMethod =
mono_class_get_method_from_name(monoClass, methodName, 1);
    if (!tempGenericMethod) {
        abort();    // passes
    }
    
    // get the method by descriptor
    
    tempGenericMethod = nil;
     // note the method looses the generic suffix
    methodName =
":ToList(System.Collections.Generic.IEnumerable`1<TSource>)";
    MonoMethodDesc *methodDesc = mono_method_desc_new(methodName, YES);
    while (monoClass != NULL) {
        tempGenericMethod = mono_method_desc_search_in_class(methodDesc,
monoClass);
        if (tempGenericMethod != NULL) {
            break;
        }
        monoClass = mono_class_get_parent(monoClass);
    }
    
    if (!tempGenericMethod) {
        abort();    // passes
    }
    
     
    // by reflection get MethodInfo for generic method
    DBMonoEnvironment *env = [DBMonoEnvironment currentEnvironment];
    MonoReflectionMethod* methodInfo =
mono_method_get_object(env.monoDomain, tempGenericMethod, monoClass);
    NSAssert(methodInfo, @"invalid");
    
    // get generic helper class 
    MonoClass *helpMonoClass = [DBMonoEnvironment
dumbartonMonoClassWithName:"Dumbarton.GenericHelper"];
    NSAssert(helpMonoClass, @"invalid");

    // get method to retrieve generic argument type at index
    MonoMethod *genericArgTypehelperMethod =
mono_class_get_method_from_name(helpMonoClass, "GenericArgumentTypeAtIndex",
2);
    NSAssert(genericArgTypehelperMethod, @"invalid");

    // get generic method parameter type info
    MonoObject *monoException = NULL;
    int idx = 0;
    MonoType *t = mono_class_get_type([self monoClass]);    // say ObjectSet
    NSLog(@"Class type name : %s", mono_type_get_name(t));
    void *hargs [2];
    hargs [0] = mono_type_get_object(env.monoDomain, t);
    hargs [1] = &idx;
    MonoObject *boxedGenericType =
mono_runtime_invoke(genericArgTypehelperMethod, NULL, hargs,
&monoException);
    NSAssert(boxedGenericType, @"invalid");
    MonoType *genericParameterType =  *(MonoType**) mono_object_unbox
(boxedGenericType);
    
    MonoMethod *helperMethod =
mono_class_get_method_from_name(helpMonoClass, "MakeGenericMethod_1", 2);
    NSAssert(helperMethod, @"invalid");

    // invoke the generic helper method
    monoException = NULL;
    hargs [0] = methodInfo;
    hargs [1] = mono_type_get_object(env.monoDomain, genericParameterType);
    MonoObject *boxedGenericMethod = mono_runtime_invoke(helperMethod, NULL,
hargs, &monoException);
    
    /*
        mono_runtime_invoke always a returns a MonoObject *.
        Un boxing gives us a pointer to the value, a MonoMethod*.
        Dereferencing this gives the method pointer.
     */
    MonoMethod *genericMethod =  *(MonoMethod**) mono_object_unbox
(boxedGenericMethod);
    NSAssert(genericMethod, @"invalid");
    
    monoException = NULL;
    void *args [1];
    args [0] = [self monoObject];   // an instance of say ObjectSet
    MonoObject *monoObject = mono_runtime_invoke(genericMethod, NULL, args,
&monoException);
    NSAssert(monoObject, @"invalid");
    
    MonoClass *resultMonoClass = mono_object_get_class(monoObject);
    MonoType *resultTypeName = mono_class_get_type(resultMonoClass);
    NSLog(@"Result type name : %s", mono_type_get_name(resultTypeName));
    
    return monoObject;
}

// Mono helper
using System;
using System.Reflection;
using System.Collections;

namespace Dumbarton
{
	public class GenericHelper
	{
		//
		// Generic method helpers
		//
		public static IntPtr MakeGenericMethod(MethodInfo method, Type[] parms)
		{
			// See MSDN's MethodInfo.MakeGenericMethod docs
			MethodInfo methodInfo = method.MakeGenericMethod (parms);
			return methodInfo.MethodHandle.Value;
		}

		public static IntPtr MakeGenericMethod_1(MethodInfo method, Type parm0)
		{
			MethodInfo methodInfo = method.MakeGenericMethod (parm0);
			return methodInfo.MethodHandle.Value;
		}

		public static IntPtr MakeGenericMethod_2(MethodInfo method, Type parm0,
Type parm1)
		{
			MethodInfo methodInfo = method.MakeGenericMethod (parm0, parm1);
			return methodInfo.MethodHandle.Value;		
		}

		public static IntPtr MakeGenericMethod_3(MethodInfo method, Type parm0,
Type parm1, Type parm2)
		{
			MethodInfo methodInfo = method.MakeGenericMethod (parm0, parm1, parm2);
			return methodInfo.MethodHandle.Value;		
		}

		//
		// Generic argument helpers
		//
		private static Type[] GenericArgumentTypes(Type t)
		{
			Type[] types = null;
			if (t.ContainsGenericParameters) {
				types = t.GetGenericArguments ();
			}
			return types;
		}

		public static IntPtr GenericArgumentTypeAtIndex(Type t, int index)
		{
			IntPtr ptrType = new IntPtr(0);
			Type[] genericTypes = t.GetGenericArguments();
			if (genericTypes != null & index < genericTypes.Length) {
				Type argType = genericTypes[index];
				ptrType = argType.TypeHandle.Value;
			}
			return ptrType;
		}
	}
}



--
View this message in context: http://mono.1490590.n4.nabble.com/Embedded-API-Method-signature-not-found-with-generic-parameter-tp4660157p4660215.html
Sent from the Mono - General mailing list archive at Nabble.com.


More information about the Mono-list mailing list