浅谈 MetadataToken

本文详细介绍了MetadataToken的概念及其在.NET框架中的应用。MetadataToken是用于标识元数据表中各种元素(如类型、方法等)的位置信息。文章通过实例展示了如何获取类型对应的MetadataToken,并解释了其结构及用途。
部署运行你感兴趣的模型镜像

原文在这里

 

概念: 要说MetadataToken,首先的先说说Metadata,MSDN对Metadata的定义是这样的“Metadata refers to declarative information about abstractions, including runtime types (classes, value types, and interfaces),  global functions, and global variables.”  (这里就不做翻译了,怕翻译不好造成误解)而对于这些Runtime的类型信息存贮在Metadata的一张张表中,我们知道这些表有定义表、引用表、指针表、堆。那么MetadataToken是什么呢?MetadataToken其实就是这些存贮在Metadata一张张表中的位置信息,它指向的就是这些表中的一个记录。对于Metadata Engine 来说,可以用这些Token去定位具体的一个Runtime Type。

   深入:MetadataToken的结构就是一个4字节的int型整数,第一个字节指出这个MetadataToken指向的RuntimeType存贮在具体的哪一个Metadata表。 对于每个Metadata表的索引值由CorTokenType这个Enum来决定,CorTokenType的定义如下:

typedef  enum  CorTokenType {

    mdtModule                       
=   0x00000000 ,
    mdtTypeRef                      
=   0x01000000 ,
    mdtTypeDef                      
=   0x02000000 ,
    mdtFieldDef                     
=   0x04000000 ,
    mdtMethodDef                    
=   0x06000000 ,
    mdtParamDef                     
=   0x08000000 ,
    mdtInterfaceImpl                
=   0x09000000 ,
    mdtMemberRef                    
=   0x0a000000 ,
    mdtCustomAttribute              
=   0x0c000000 ,
    mdtPermission                   
=   0x0e000000 ,
    mdtSignature                    
=   0x11000000 ,
    mdtEvent                        
=   0x14000000 ,
    mdtProperty                     
=   0x17000000 ,
    mdtModuleRef                    
=   0x1a000000 ,
    mdtTypeSpec                     
=   0x1b000000 ,
    mdtAssembly                     
=   0x20000000 ,
    mdtAssemblyRef                  
=   0x23000000 ,
    mdtFile                         
=   0x26000000 ,
    mdtExportedType                 
=   0x27000000 ,
    mdtManifestResource             
=   0x28000000 ,
    mdtGenericParam                 
=   0x2a000000 ,
    mdtMethodSpec                   
=   0x2b000000 ,
    mdtGenericParamConstraint       
=   0x2c000000 ,
    mdtString                       
=   0x70000000 ,
    mdtName                         
=   0x71000000 ,
    mdtBaseType                     
=   0x72000000

} CorTokenType;

 具体每一个enum值代表什么我就不用说了,相比聪明的你一看就明白了。从CorTokenType的定义,机灵的读者会发现其实每个表里只能有16777216条记录。就mdtTypeDef来说,我们可不可以说在一个Module中我们最多只能定义16777216个type呢?!扯的有些远了,我们回到刚才的对MetadataToken结构的讨论。4字节的MetadataToken的后三个字节在其实就是一个RuntimeType在具体一个Metadata表中的位置,或者说是偏移量吧。 口说无凭,还是我们来点实际的吧!

   例子 : 我们建一个简单的Console工程就可以了,定义一下三个type:

using  System;
namespace  ConsoleApplication3
{
    
interface  IClass1
    {
        
void  Fun1();
    }
}


using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  ConsoleApplication3
{
    
class  Class1 : ConsoleApplication3.IClass1
    {
        
public   void  Fun1()
        {
        }
    }
}


using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Runtime.Serialization;

namespace  ConsoleApplication3
{
    
class  Program
    {
        
static   void  Main( string [] args)
        {
            Console.WriteLine(
" typeof(Class1).MetadataToken = {0} " , Convert.ToString(
                                                                        
typeof (Class1).MetadataToken,  16 )
                                                                        );

            Console.WriteLine(
" typeof(IClass1).MetadataToken = {0} " , Convert.ToString(
                                                                      
typeof (IClass1).MetadataToken,  16 )
                                                                      );

            Console.WriteLine(
" typeof(Program).MetadataToken = {0} " , Convert.ToString(
                                                                      
typeof (Program).MetadataToken,  16 )
                                                                      );

            Console.Read();
        }
    }
}

 

我们先不要急着去Run它,我们可以用前面说的这些知识来分析,然后猜想一下结果。因为这三个都是类型,所以他们的MetadataToken的第一个字节肯定是0x020000, 因为这个项目里面只有三个类型,所以我想他们的MetadataToken肯定是0x0200002、0x02000003, 0x02000004(有一个很重要的忘说了,在每张Metadata表中的0位置是不包含数据的,MSDN说成为nil token, 0x02000001这个位置预留给了一个名为<Module>的特殊类型。程序中所有的全局字段和全局方法,其实都是这个<Module>类型的成员(这里多谢 Anders Liu 帮忙指正,谢谢)),现在我们可以看看结果了啊

和我们预计结果一致。其他的我就不举例了,有兴趣的朋友可以自己试试,这里要注意的是一点就是String类型的MetadataToken的后三个字节的代表的是这个string在Metadata string pool中的起始位置。

      应用: 讲了这么多了,到底这个东东有什么用呢?该怎么样用呢?对于一个已经build的程序集,它其中的Metadata已经固定了,也就是说它的MetadataToken是固定。这样的话,有的时候我们就可以直接通过这个MetadataToken去获得它的RuntimeType,这点在泛型和反射有的时候是非常有用的。具体的使用如下:

            Module currentModule  =  Assembly.GetExecutingAssembly().GetModules()[ 0 ];

            ModuleHandle currentModuleHandle 
=  currentModule.ModuleHandle;

            
int  token  =   typeof (Program).MetadataToken;

            RuntimeTypeHandle rth 
=  currentModuleHandle.GetRuntimeTypeHandleFromMetadataToken(token);

            Type currentType 
=  Type.GetTypeFromHandle(rth);

    

           就写到这了,其实Metadata还是很值得仔细学习一下,我现在了解的还是很肤浅,这里也只是抛砖引玉,希望得到高手的拍砖, 哈哈哈。。。。

您可能感兴趣的与本文相关的镜像

HunyuanVideo-Foley

HunyuanVideo-Foley

语音合成

HunyuanVideo-Foley是由腾讯混元2025年8月28日宣布开源端到端视频音效生成模型,用户只需输入视频和文字,就能为视频匹配电影级音效

【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)内容概要:本文介绍了基于蒙特卡洛和拉格朗日方法的电动汽车充电站有序充电调度优化方案,重点在于采用分散式优化策略应对分时电价机制下的充电需求管理。通过构建数学模型,结合不确定性因素如用户充电行为和电网负荷波动,利用蒙特卡洛模拟生成大量场景,并运用拉格朗日松弛法对复杂问题进行分解求解,从而实现全局最优或近似最优的充电调度计划。该方法有效降低了电网峰值负荷压力,提升了充电站运营效率经济效益,同时兼顾用户充电便利性。 适合人群:具备一定电力系统、优化算法和Matlab编程基础的高校研究生、科研人员及从事智能电网、电动汽车相关领域的工程技术人员。 使用场景及目标:①应用于电动汽车充电站的日常运营管理,优化充电负荷分布;②服务于城市智能交通系统规划,提升电网交通系统的协同水平;③作为学术研究案例,用于验证分散式优化算法在复杂能源系统中的有效性。 阅读建议:建议读者结合Matlab代码实现部分,深入理解蒙特卡洛模拟拉格朗日松弛法的具体实施步骤,重点关注场景生成、约束处理迭代收敛过程,以便在实际项目中灵活应用改进。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值