.winmd 文件平台独立吗?

Is .winmd file platform independent?

我已经为通用Windows[=62=开发了一个基于C/C++的Windows运行时组件 ],我现在正尝试将其包含在 NuGet 插件中。

在 NuGet 版本 3 中,引入了 runtimes 文件夹,有关详细信息,请参阅 here。不幸的是,该文档没有提供太多关于如何处理 Windows 运行时组件s.

的信息

我是这样组织 NuGet 包中的文件的:

└───MyNuGetPackage  
     ├───lib  
     │   └───uap  
     │         MyRuntimeLibrary.winmd  
     │  
     ├───build  
     │   └───uap  
     │         MyNuGetPackage.targets  
     │  
     └───runtimes  
         ├───win10-x86  
         │   └───native  
         │         MyRuntimeLibrary.dll  
         │  
         ├───win10-x64  
         │   └───native  
         │         MyRuntimeLibrary.dll  
         │  
         └───win10-arm  
             └───native  
                   MyRuntimeLibrary.dll  

MyNuGetPackage.targets文件在构建过程中用于添加对.winmd文件的引用并明确指定实现 .dll:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences">
    <ItemGroup Condition=" '$(Platform)' == 'x86' or '$(Platform)' == 'x64' or '$(Platform)' == 'ARM'">
      <Reference Include="Dicom.Imaging.Codec">
        <HintPath>$(MSBuildThisFileDirectory)..\..\lib\uap\MyRuntimeLibrary.winmd</HintPath>
        <Implementation>MyRuntimeLibrary.dll</Implementation>
      </Reference>
    </ItemGroup>
  </Target>  
</Project>

据我所知,这个 NuGet 包组合有效;针对不同平台x86x64ARM.[=构建时选择相关的实现文件14=]

但是,通过上述方法,我只包括来自一个目标平台的 .winmd 文件(在这种特定情况下为 x86 ). 这真的可以吗? 看起来可行,但 .winmd 文件平台真的独立吗?


如果 .winmd 文件依赖于平台 ,我尝试添加平台目标特定 .winmd 文件在 runtimes 文件夹下,像这样:

     └───runtimes  
         ├───win10-x86  
         │   └───lib  
         │       └───uap  
         │             MyRuntimeLibrary.winmd  
         │   └───native  
         │         MyRuntimeLibrary.dll  

并且我已经相应地更新了 MyNuGetPackage.targets 文件。但是,当我安装这个替代的 NuGet 包并尝试为特定平台构建时,我收到一个有效负载构建错误,表明 MyRuntimeLibrary.winmd 文件被复制到输出目录两个不同的位置,lib\uap 文件夹和 runtimes 子文件夹。

完全排除顶部 lib\uap 文件夹也无济于事;如果这样做,构建过程根本找不到任何 .winmd 文件引用。

如果 .winmd 文件毕竟是平台相关的,我应该如何组织 .winmd。我的 NuGet 包中的 dll 个文件以确保该包在所有平台上都能充分安装?

这可能有助于理解 .winmd 文件的真正含义。它是对旧 COM 类型库的重新表述,您之前可能将 运行 放入 .tlb 文件中。之前可能已经使用 OleView.exe SDK 实用程序、File + View Typelib 命令查看了它的内容。

与 .NET 元数据非常相似,您的个人资料表明您以前肯定使用过它们。您在 C# 项目的引用节点中找到的文件。您之前可能已经使用 ildasm.exe 或 Reflector 或 ILSpy 等 .NET 反编译器查看过它们。或者 IDE 的 Go To Declaration 命令。您已经知道此类引用与平台无关。

Microsoft 淘汰了 .tlb 文件格式并用 .NET 元数据文件格式取而代之。一种足够灵活的格式,也可以表达 COM 声明。并且可扩展到足以表达 WinRT 声明,这种声明不能被写入 .tlb 格式。与泛型和属性一样,语言投影 大量使用它们来使 COM 客户端代码更易于编写。非常好的举措,Microsoft 只需很少的工作即可更改现有工具(如 C# 编译器)以处理 .winmd 文件。

长话短说,它在编译时的行为就像 .NET 程序集和 COM 类型库。编译器使用它来检索类型声明。您 可以 不小心使其依赖于平台,例如在您打算使用 IntPtr 时使用 int。但是无论您使用何种语言进行编程,语言投影都会使这种情况变得非常罕见。并且在你测试的时候很快发现。