You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Mono运行时通过C++获取C#类的特性?

如何在C++中通过Mono运行时获取C#类的特性?

当然可以!Mono运行时提供了全套API来访问.NET元数据,包括类上标注的特性。我会结合你的示例代码,一步步带你实现从C++中探测C#类的特性并处理的流程。

第一步:C#端的准备工作

首先确保你的自定义特性符合.NET规范,比如:

using System;

// 标记特性可用于类
[AttributeUsage(AttributeTargets.Class)]
public class SomeAttribute : Attribute
{
    // 可选:添加特性的属性或构造参数
    public string Tag { get; set; }

    public SomeAttribute() {}
    public SomeAttribute(string tag) => Tag = tag;
}

// 标注了特性的目标类
[SomeAttribute("DemoClass")]
public class SomeClass 
{
    // 类内容...
}

注意要保证特性是public的且继承自System.Attribute,这样Mono才能正确识别并访问它的元数据。

第二步:C++端通过Mono API获取特性

假设你已经完成了Mono运行时的基础初始化(比如创建应用域、加载程序集),下面是核心操作步骤:

1. 加载程序集并获取目标类

首先加载包含SomeClass的程序集,再获取对应的MonoClass指针:

#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/class.h>
#include <mono/metadata/object.h>
#include <mono/metadata/attrdefs.h>

// 初始化Mono运行时(基础操作,你应该已经完成)
MonoDomain* domain = mono_jit_init("YourAppDomain");
// 加载目标程序集(替换为你的程序集路径)
MonoAssembly* assembly = mono_domain_assembly_open(domain, "YourAssembly.dll");
MonoImage* image = mono_assembly_get_image(assembly);

// 获取SomeClass的MonoClass(注意替换为实际的命名空间)
MonoClass* some_class = mono_class_from_name(image, "YourNamespace", "SomeClass");
if (!some_class) {
    // 处理类不存在的错误
    return -1;
}

2. 获取类上的所有自定义特性

使用mono_class_get_custom_attributes函数获取类上的特性集合,返回一个MonoArray对象:

// 获取类上的自定义特性(第二个参数FALSE表示不获取继承来的特性)
MonoArray* attributes = mono_class_get_custom_attributes(some_class, FALSE);
if (!attributes) {
    // 类没有标注任何特性,直接返回
    return 0;
}

// 获取特性数组的长度
int attr_count = mono_array_length(attributes);

3. 遍历特性并识别目标特性

先获取SomeAttribute对应的MonoClass,再遍历数组判断每个特性是否是我们要找的类型:

// 获取SomeAttribute的MonoClass(注意命名空间要匹配)
MonoClass* some_attr_class = mono_class_from_name(image, "YourNamespace", "SomeAttribute");
if (!some_attr_class) {
    // 处理特性类不存在的错误
    return -1;
}

for (int i = 0; i < attr_count; i++) {
    // 从数组中取出特性对象
    MonoObject* attr_obj = mono_array_get(attributes, MonoObject*, i);
    
    // 判断当前特性是否是目标类型
    if (mono_object_is_instance_of_type(attr_obj, some_attr_class)) {
        // 找到目标特性,执行你的业务逻辑
        printf("检测到SomeAttribute!\n");

        // (可选)读取特性的属性值,比如Tag
        MonoClassField* tag_field = mono_class_get_field_from_name(some_attr_class, "Tag");
        if (tag_field) {
            // 获取字段值(string类型返回MonoString*)
            MonoString* tag_str = (MonoString*)mono_field_get_value_object(domain, tag_field, attr_obj);
            // 转换为C字符串
            const char* tag = mono_string_to_utf8(tag_str);
            printf("特性的Tag值:%s\n", tag);
            // 记得释放C字符串
            mono_free((void*)tag);
        }

        // 如果特性有方法,也可以用mono_runtime_invoke调用
    }
}

4. 清理资源

根据程序生命周期,及时释放Mono相关资源:

// 释放特性数组对象
mono_object_unref((MonoObject*)attributes);
// 关闭程序集、销毁应用域等
mono_assembly_close(assembly);
mono_jit_cleanup(domain);

关键注意事项

  • 命名空间匹配:获取类和特性时必须指定正确的命名空间,否则会找不到对应类型。
  • 继承特性控制:如果需要获取父类继承的特性,把mono_class_get_custom_attributes的第二个参数设为TRUE。
  • 资源管理:Mono对象需要正确管理引用,用mono_object_unref释放不再使用的对象,避免内存泄漏。
  • 访问权限:自定义特性必须是public的,否则Mono无法访问其元数据。

这样你就能在C++中成功探测到C#类上的特性,并执行相应操作了!

内容的提问来源于stack exchange,提问作者Nikita Kozhevnikov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:58:58