2013-07-13 30 views
6

Làm cách nào để tạo một đối tượng chung Danh sách < Chuỗi > bằng cách sử dụng các cuộc gọi được nhúng mono? Tôi có thể lấy Danh sách của MonoClass:Nhận loại chung bằng Mono được nhúng

MonoClass* list = mono_class_from_name(mscorlibimage, 
    "System.Collections.Generic", "List`1"); 

và tôi thấy trong tài liệu rằng có

mono_class_from_generic_parameter(MonoGenericParam*...) 

nhưng tôi không có ý tưởng ở đâu và làm thế nào để có được MonoGenericParam. Hoặc có lẽ tôi cần phải xây dựng một tên hợp lệ cho mono_class_from_name? Tôi nghĩ rằng điều này có thể chậm hơn một chút nhưng tôi chấp nhận điều đó ngay bây giờ. Tôi đã thử

MonoClass* list = mono_class_from_name(mscorlib::get().image, "System.Collections.Generic", "List`1[System.String]"); 

nhưng không may mắn.

CẬP NHẬT:

OK Tôi đã tìm được cách. Tôi vẫn muốn xem liệu có cách nào để thực hiện điều này không, vì hack này có vẻ quá bẩn đối với tôi.

Về cơ bản, tôi đã tìm kiếm các nguồn mono cho các phương thức chung và tìm thấy mono_class_bind_generic_parameters (xem https://raw.github.com/mono/mono/master/mono/metadata/reflection.c). Tôi đã phải liên kết với libmono-2.0.a ngoài .so để sử dụng nó. Nhưng nó làm việc:

extern "C" MonoClass* 
mono_class_bind_generic_parameters(MonoClass *klass, 
    int type_argc, MonoType **types, bool is_dynamic); 

MonoClass* list = mono_class_from_name(mscorlib::get().image, 
    "System.Collections.Generic", "List`1"); 
MonoClass* strcls = mono_class_from_name(mscorlib::get().image, "System", "String"); 
printf("str class: %p\n", strcls); 
MonoType* strtype = mono_class_get_type(strcls); 
printf("str type: %p\n", strtype); 
MonoType* types[1]; 
types[0] = strtype; 
list = mono_class_bind_generic_parameters(list, 1, types, false); 
printf("list[string] class: %p\n", list); 
MonoObject* obj = mono_object_new(domain, list); 
printf("list[string] created: %p\n", obj); 

Tôi cho rằng tôi có thể mất nguồn (UPDATE: hầu như không như vậy) của các phương pháp và reimplement họ (họ phân tích siêu dữ liệu, vv) - nếu tôi không muốn liên kết đến .a - nhưng Tôi tự hỏi nếu có một cách đơn giản hơn. Tài liệu đơn thuần không trả lời bất cứ điều gì, khi chúng sử dụng.

CẬP NHẬT: đã tìm thấy chuỗi này: http://mono.1490590.n4.nabble.com/Embedded-API-Method-signature-not-found-with-generic-parameter-td4660157.html dường như không có API nhúng nào tồn tại cho những gì tôi muốn (nghĩa là chúng không bận tâm để hiển thị mono_class_bind_generic_parameters). Ai đó có thể chứng minh rằng đó là chính xác? Với phương pháp đó, bằng cách này, tôi nhận được MonoReflectionType * và không có cách nào để lấy lại MonoType * từ nó - trong khi nó dễ dàng như việc -> gõ từ cấu trúc - đó là nội bộ và truy cập thông qua các hàm cho nó là nội bộ. Mono Embedded nên được gọi là "Mono Internal" để thay thế.

UPDATE: phương pháp khác là hack mono_class_inflate_generic_type sử dụng bản sao của cấu trúc nội bộ:

struct _MonoGenericInst { 
     uint32_t id;      /* unique ID for debugging */ 
     uint32_t type_argc : 22;  /* number of type arguments */ 
     uint32_t is_open  : 1;  /* if this is an open type */ 
     MonoType *type_argv [1]; 
}; 

struct _MonoGenericContext { 
     /* The instantiation corresponding to the class generic parameters */ 
     MonoGenericInst *class_inst; 
     /* The instantiation corresponding to the method generic parameters */ 
     void *method_inst; 
}; 

    _MonoGenericInst clsctx; 
    clsctx.type_argc = 1; 
    clsctx.is_open = 0; 
    clsctx.type_argv[0] = mono_class_get_type(System::String::_SClass()); 
    MonoGenericContext ctx; 
    ctx.method_inst = 0; 
    ctx.class_inst = &clsctx; 
    MonoType* lt = mono_class_inflate_generic_type(
     mono_class_get_type(System::Collections::Generic::List<System::String>::_SClass()), 
     &ctx); 

này không yêu cầu liên kết tĩnh để .a nhưng thậm chí còn tồi tệ hơn một hack. Và mono_class_inflate_generic_type được đánh dấu là DEPRECATED - vì vậy, nếu điều này không được chấp nhận, thì trong đó là kiểu hiện đại?

+0

Có thể gọi phương thức tĩnh Type.GetTypeFormTypeHandle để biến MonoType thành MonoReflectionType và gọi phương thức cá thể MakeGenericType trên đó và nhận giá trị fr om resoults thuộc tính TypeHandle mà shoud được trỏ đến MonoType. Đây chỉ là phỏng đoán tôi chưa bao giờ sử dụng Mono Embedded. – user629926

+0

Vâng, trong diễn đàn đó, tôi đã tìm ra cách liên quan đến việc sử dụng TypeHandle IntPtr và unboxing nó. Đây là cách an toàn nhất mà không có hack, nhưng việc sử dụng C# helpers chỉ để tạo kiểu nhúng trông hơi khó xử với tôi. – queen3

+0

Đây là câu hỏi hay khi được hỏi tại danh sách gửi thư đơn điệu (http://lists.ximian.com/mailman/listinfo/mono-devel-list) –

Trả lời

1

Trong nhiều trường hợp, vấn đề hóc búa đơn lẻ có thể được giải quyết bằng cách sử dụng phương thức trợ giúp được quản lý. Đây là cách tiếp cận được sử dụng ở đây.

Vì vậy, chúng ta có:

  1. Một quản lý phương pháp helper chấp nhận một định nghĩa kiểu chung chung và một loạt các loại tham số chung.

  2. Phương thức khách hàng chấp nhận tên định nghĩa loại chung (ví dụ: System.Collections.Generic.List`1), một hình ảnh lắp ráp có chứa loại (hoặc sử dụng tên Hội đủ điều kiện) và đối tượng được yêu cầu loại tham số chung. Chúng ta lấy ra monoType bên dưới cho đối tượng.

Lưu ý rằng khi chuyển thông tin loại vào lớp được quản lý, nó phải là một thể hiện của MonoReflectionType như thu được từ mono_type_get_object().

Phương pháp helper quản lý là tầm thường và không instantiation thực tế:

public static object CreateInstanceOfGenericType(Type genericTypeDefinition, Type[] parms) 
    { 
     // construct type from definition 
     Type constructedType = genericTypeDefinition.MakeGenericType(parms); 

     // create instance of constructed type 
     object obj = Activator.CreateInstance(constructedType); 

     return obj; 
    } 

Mã helper được gọi là, trong trường hợp này, từ Objective-C:

+ (id)createInstanceOfGenericTypeDefinition:(char *)genericTypeDefinitionName monoImage:(MonoImage *)monoImage itemObject:(id)itemObject 
{ 
    // get the contained item monoType 
    MonoType *monoType = [DBType monoTypeForMonoObject:[itemObject monoObject]]; 
    MonoReflectionType *monoReflectionType = mono_type_get_object([DBManagedEnvironment currentDomain], monoType); 

    // build a System.Array of item types 
    DBManagedObject *argType = [[DBManagedObject alloc] initWithMonoObject:(MonoObject *)monoReflectionType]; 
    NSArray *argTypes = @[argType]; 
    DBSystem_Array *dbsAargTypes = [argTypes dbsArrayWithTypeName:@"System.Type"]; 

    // get the generic type definition 
    // 
    // Retrieves a MonoType from given name. If the name is not fully qualified, 
    // it defaults to get the type from the image or, if image is NULL or loading 
    // from it fails, uses corlib. 
    // This is the embedded equivalent of System.Type.GetType(); 
    MonoType *monoGenericTypeDefinition = mono_reflection_type_from_name(genericTypeDefinitionName, monoImage); 

    // create instance using helper method 
    MonoMethod *helperMethod = [DBManagedEnvironment dubrovnikMonoMethodWithName:"CreateInstanceOfGenericType" className:"Dubrovnik.FrameworkHelper.GenericHelper" argCount:2]; 
    void *hargs [2]; 
    hargs[0] = mono_type_get_object([DBManagedEnvironment currentDomain], monoGenericTypeDefinition); 
    hargs[1] = [dbsAargTypes monoArray]; // a monoArray * 

    MonoObject *monoException = NULL; 
    MonoObject *monoObject = mono_runtime_invoke(helperMethod, NULL, hargs, &monoException); 
    if (monoException) NSRaiseExceptionFromMonoException(monoException); 

    id object = [System_Object subclassObjectWithMonoObject:monoObject]; 

    return object; 
} 

Đối với mã hoàn chỉnh thấy Dubrovnik trên Github

Các vấn đề liên quan