Reflection IMetaDataImport和WinRT runtimeclass接口

Reflection IMetaDataImport和WinRT runtimeclass接口,reflection,windows-runtime,idl,Reflection,Windows Runtime,Idl,在Visual Studio 2012附带的MS IDL版本中,对WinRT的支持添加了以下构造: [activatable(Windows.Networking.Sockets.IControlChannelTriggerFactory, 0x06020000)] [threading(mta)] [marshaling_behavior(agile)] [version(0x060200

在Visual Studio 2012附带的MS IDL版本中,对WinRT的支持添加了以下构造:

        [activatable(Windows.Networking.Sockets.IControlChannelTriggerFactory,
                     0x06020000)]
        [threading(mta)]
        [marshaling_behavior(agile)]
        [version(0x06020000)]
        runtimeclass ControlChannelTrigger
        {
            [default] interface Windows.Networking.Sockets.IControlChannelTrigger;
            interface Windows.Foundation.IClosable;
        }
我正在使用IMetaDataImport分析winmd文件中的所有类型。如何确定“runtimeclass”实现了哪些接口,以及默认接口是哪个接口

如何找出“运行时类”实现的接口

Windows元数据文件由关系数据库组成:它基本上是一组相互关联的表。您可以在的分区II中找到逻辑模式的规范

每个运行时类和接口都由元数据数据库的TypeDef表中的一行表示。“类型X实现接口I和J”关系由InterfaceImpl表中的行表示,该表将类型定义映射到它们实现的接口

事实证明,计算由类型实现的接口集是相当困难的,原因有很多。假设我们要计算由XAML控件实现的接口集。需要执行以下所有步骤:

  • 查找并加载定义
    按钮
    的元数据文件。你可以打电话来

  • 查找
    按钮
    类型的元数据标记。这实际上是该类型的唯一标识符。你可以打电话来

  • 我们需要计算由
    按钮直接实现的所有接口。这可以通过打电话来完成

  • 按钮
    类型派生自该类型。这是由TypeDef表的extends字段指定的,您可以通过调用来获得该字段。我们需要计算它实现的所有接口。然后,我们需要在类层次结构中一直执行相同的操作——对于
    按钮
    ,有很多类型:
    内容控件
    控件
    框架元素
    UIElement
    ,和
    依赖对象

    请注意,其中一些类型可能在另一个元数据文件中定义。在这种情况下,InterfaceImpl将通过TypeRef令牌而不是TypeDef令牌引用接口。TypeRef表包含对类型的引用。您需要解析该引用,加载正确的元数据文件,并在该元数据文件中找到目标类型。这可以使用我们已经为
    按钮执行的步骤来完成

  • 每个接口也可以实现其他接口,因此对于我们迄今为止在列表中积累的每个接口,我们需要获得该接口所需的接口集。这是通过递归获取每个接口的InterfaceImpl来实现的

    注意,与基类一样,实现的接口也可以在另一个元数据文件中定义。因此,您还需要使用与基类相同的过程来解决这些问题

    对于一个额外的挑战,Windows运行时支持通用接口。如果一个接口实现了一个实例化的泛型接口,那么该实例化接口将由TypeSpec表中的一行表示,并在blob流中伴随一个签名。您将需要解析签名。执行此操作的过程相当复杂,但ECMA 335中完全指定了数据格式

  • 此时,您将拥有由该类型实现的完整接口集。通过检查与
    按钮
    类型直接关联的InterfaceImpl,可以找到默认接口:默认接口将应用该属性(请注意,自定义属性应用于InterfaceImpl,而不是接口类型)。可以使用枚举每个InterfaceImpl的自定义属性

    所以,这是一个非常多的工作,它需要大量的代码。我发现
    imeadataimport
    接口及其好友的处理方式非常不友好,因此我为Boost编写了自己的。CxxReflect元数据库提供了比IMetaDataImport更好的类型检查,并包含解析签名所需的逻辑。它的速度不如IMetaDataImport,但正在接近

    CxxReflect反射库包含用于跨元数据文件边界解析类型以及与Windows运行时集成的大部分逻辑。它仍处于alpha质量阶段,但对于普通任务来说效果很好(它目前正在进行一些重构,以使类型解析逻辑可用于反射以外的用途)


    您当然可以自己实现逻辑来完成这项工作,但这非常繁琐。在CxxReflect的开发过程中,我多次发现了另一个我没有考虑的问题,不得不进行大量的返工。规范是完整的,但并不总是很清楚应该如何工作。

    顺便说一句,带有DefaultAttribute的接口将是RuntimeClass用作API参数时使用的接口。谢谢:EnumInterfaceImpls实际上就是我想要的。在我的例子中,所有其他继承的情况都将很自然地消失,因为它将映射到多重继承(在Python中)。@Martinv.Löwis:您正在构建Python语言投影吗?@Martinv.Löwis:很好!听起来很有趣。:-)