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

jonathan at mugginsoft.com jonathan at mugginsoft.com
Fri Jul 12 13:06:15 UTC 2013


> You must "inflate" the generic method upon invocation.
> IIRC, there is no function in the embedded API which does this.
There is mono_class_inflate_generic_method() but this requires a MonoGenericContext.

I am attempting to call the generic method ObjectSet.ToList().
The code below employs inflation and runs to completion but returns a NULL result.
I have verified by calling non generic methods that the object does contain objects.

So something is not quite kosher yet.

    // ToList() is a LINQ extension method defined in System.Core
    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;
    const char *className = mono_class_get_name(monoClass);
    
    [DBMonoObjectRepresentation logMonoClassInfo:monoClass];
    
    // mono_class_get_method_from_name takes a simple method name
    const char *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();    // fails
    }
    
    // get the generic parameter info
    MonoObject *genericParameter = [self monoObject];
    MonoType *genericParameterType = mono_class_get_type([self monoClass]);
    NSAssert(genericParameterType, @"invalid"); // passes
    
//
// Inflation
//
    // by reflection get MethodInfo for generic method
    DBMonoEnvironment *env = [DBMonoEnvironment currentEnvironment];
    MonoReflectionMethod* methodInfo = mono_method_get_object(env.monoDomain, tempGenericMethod, monoClass);
    NSAssert(methodInfo, @"invalid"); // passes
    
    // get generic helper class and method
    MonoClass *helpMonoClass = [DBMonoEnvironment dumbartonMonoClassWithName:"Dumbarton.GenericHelper"];
    NSAssert(helpMonoClass, @"invalid");
    MonoMethod *helperMethod = mono_class_get_method_from_name(helpMonoClass, "MakeGenericMethod_1", 2);
    NSAssert(helperMethod, @"invalid"); // passes

    // invoke the generic helper method
    MonoObject *monoException = NULL;
    void *hargs [2];
    hargs [0] = methodInfo;
    hargs [1] = mono_type_get_object(env.monoDomain, genericParameterType);
    MonoMethod *genericMethod = (MonoMethod *)mono_runtime_invoke(helperMethod, NULL, hargs, &monoException);
    NSAssert(genericMethod, @"invalid"); // passes
    
    monoException = NULL;
    void *args [1];
    args [0] = genericParameter;
    // we are invoking a static generic method, hence the NULL
    MonoObject *monoObject = mono_runtime_invoke(genericMethod, NULL, args, &monoException);
    NSAssert(monoObject, @"invalid"); // fails, but the cigar awaits

Jonathan












More information about the Mono-list mailing list