精简版
使用IMetadataImport时如何从文件中获取与枚举关联的数值?*.winmd
一个很好的例子是ApplicationHighContrastAdjustment枚举:
//Windows.UI.Xaml.ApplicationContrastMode (@020000006)
public enum ApplicationHighContrastAdjustment : uint
{
None = 0u,
Auto = 4294967295u
}
大多数枚举是0, 1, 2, ...
. 但是这个在枚举成员上指定了其他值:
- 0
- 4294967295
我如何阅读获取那些UInt32值
注意:这个问题不一定只适用于 WinRT。在 C# 世界中使用相同的接口来检查 .NET 托管程序集。WinRT 恰好使用相同的程序集文件格式。
长版
我IMetadataImport
用来阅读*.winmd
(用于 WinRT 应用程序的现代版 TLB)的内容。但这个问题同样适用于阅读有关 .NET 托管程序集的元数据。
如何启动和运行读取 winmd 元数据文件的精简版:
// Create your metadata dispenser:
IMetadataDispsener dispener;
MetaDataGetDispenser(CLSID_CorMetaDataDispenser, IMetaDataDispenser, out dispenser);
//Open the winmd file we want to dump
String filename = "C:\Windows\System32\WinMetadata\Windows.UI.Xaml.winmd";
IMetaDataImport reader; //IMetadataImport2 supports generics
dispenser.OpenScope(filename, ofRead, IMetaDataImport, out reader); //"Import" is used to read metadata. "Emit" is used to write metadata.
获取有关枚举的信息(自动,无)
我们现在有一个读者。而不是枚举程序集中的类型,我可以直接跳到这个问题的有趣问题0x02000006
::
//Get metadata for enum Windows.UI.Xaml.ApplicationHighContrastAdjustment
mdToken tokenID = 0x02000006; //Windows.UI.Xaml.ApplicationHighContrastAdjustment
//btw, this is all hypothetical code that is vaguely C#/Java-like.
Pointer enum = null;
mdToken memberID;
int nCount;
while (reader.EnumMembers(ref enum, tokenID, out memberID, 1, out nCount) == S_OK)
{
//out MemberID receives the TokenID of each member of the enumeration
}
reader.CloseEnum(enum);
调用EnumMembers
返回枚举的三个成员:
- Windows.UI.Xaml.ApplicationContrastMode (@02000006)
- 值__(@ 04000439 ,私人)
- 无(@0400043A,公开)
- 自动(@0400043B,公共)
获取每个枚举值的信息
我们实际上是通过调用GetMemberProps来找出他们的名字(以及一个是私有的事实):
IMetaDataImporter.GetMemberProps(0x0400043A, ...); //"None"
IMetaDataImporter.GetMemberProps(0x0400043B, ...); //"Auto"
注意:GetMemberProps 是一个辅助函数。来自微软:
这是一个简单的辅助方法:如果md是 MethodDef,那么我们调用GetMethodProps;如果md是 FieldDef,那么我们调用GetFieldProps。有关详细信息,请参阅这些其他方法。
GetMemberProps方法返回有关每个枚举值的大量信息 - 但不是它们的实际枚举值:
| Metadata | @0400043A | @0400043B |
|-------------------|-------------------|-----------------|
| Name | "None" | "Auto" |
| Attributes | 0x00008056 | 0x00008056 |
| Signature | 06 11 A3 95 | 06 11 A3 95 |
| CodeRVA | 0x00000000 | 0x00000000 |
| CPlusTypeFlag | ELEMENT_TYPE_U4 | ELEMENT_TYPE_U4 |
| DefaultValue | (none) | (none) |
我在成员属性中找不到任何指示枚举分配值的内容。并查看其他IMetadataImporter方法:
- IMetadataImporter
- GetMemberProps (GetMemberProps 是一个助手,根据类型调用 GetMethodProps 或 GetFieldProps)
- GetMethodProps
- 获取FieldProps
- 获取PropertyProps
- 获取事件道具
- 获取参数道具
- GetInterfaceImplProps
- GetCustomAttributeProps
- GetTypeDefProps
- GetTypeRefProps
- GetScopeProps
- GetPermissionSetProps
- GetModuleRefProps
- GetNestedClassProps
- GetMemberRefProps
- GetMemberProps (GetMemberProps 是一个助手,根据类型调用 GetMethodProps 或 GetFieldProps)
奖金阅读
- MSDN 博客:元数据非托管 API (一个旧 Word 文档的初步 PDF 版本,据我所知,它是元数据 API 的唯一 Microsoft 文档) (存档)