APIInformation不尊重应用程序目标版本吗?



想象以下设置:

UWP库:
Minversion:10240
目标列表:16299

此库在运行时检查是否存在Universalapicontract版本5。
如果是,它将使用新的NavigationView控件。

UWP应用程序:
Minversion:10240
目标列表:10240

此应用程序引用UWP库项目。
当我在安装Windows 10版本16299的计算机上运行此应用程序时,发生以下情况:
UWP库在运行时检查API合同。由于我有最新版本的Windows 10,是的。
然后,它试图创建NavigationView控件,并且我获得了一个带有消息的Typeloadexception,找不到Windows Runtime type'windows.ui.xaml.controls.navigations.navigationview'。

什么?为什么?APIInformation类不尊重运行应用程序的目标版本吗?

我该如何解决这个问题?
我以为是避免这种情况的方法,但显然不是吗?!

这是一个显示错误的GitHub存储库:
https://github.com/haefele/apiinformationtargetversionfail

如果将MyApp项目的目标转换设置为16299,则一切正常。

[编辑2018年5月29日]

ApiInformation类型的方法基于磁盘上的Winrt元数据的微不足道查找 - 如果元数据在那里,则调用成功。这使"点亮"启用了。新平台上的新功能,而没有增加最低版本。重要的是,ApiInformation对API的实现一无所知:有时可能会丢失(例如," OS的构建"内部构建),有时由于&quot可能无法使用。怪异(请参见下面的示例)。由于JIT和.NET本机工具链的工作方式,.NET对世界也有不同的看法。

这可能会引起问题...

.NET应用程序使用"联合Winmd"的概念。这是Windows SDK中所有已知类型(包括扩展SDK)的联合,与应用程序的MaxVersionTested设置相对应。如果您在底层平台上运行该应用程序,则ApiInformation会告诉您API不存在,但是.NET仍然可以基于Union WinMD来汇总方法并执行一些反射任务。如果您实际尝试调用API(因为您忘记了ApiInformation检查),则在运行时会获得MissingMethodException,因为API确实不存在。

如果在一个较低的应用程序中包含更高的.NET库,然后尝试在OS的较高构建中运行它,则可能会发生不同的问题。在这种情况下,ApiInformation将成功,因为系统元数据中存在类型,但是.NET会在运行时投掷MissingMethodException,因为该类型不存在用于构建应用程序的联合Winmd中。/p>

重要:这是基于的目标版本(aka MaxVersionTested),而不是库!

如果您构建了该应用程序的发行版本,您甚至会在输出窗口中看到.NET本机工具链显示这样的警告:

warning : ILTransform : warning ILT0003: Method 'Foo.Bar()' will always throw an exception due to the missing method 'SomeNewType.NewMethod()'. There may have been a missing assembly.

除了用与库相同的目标版本构建您的应用程序外,没有任何好方法(以便可以解决所有参考)。

您可能会遇到的另一个问题是,当您的应用程序(或库消耗的库)使用未来的API'在列出为应用程序的MaxVersionTested中的操作系统中不存在。许多API将起作用,但有些API由于与应用程序正在运行的模拟旧模式不兼容而不兼容。

库问题的假设示例

想象一下,操作系统的版本X仅支持黑白应用,其中背景始终是白色,文本,图形等始终是黑色的。应用程序是使用这种基本假设构建的 - 包括具有仅分配每金1位1位的图形缓冲区,或者永远不必担心文本是不可见的,因为背景和前景颜色是相同的。一切都很好。

现在,操作系统的版本y出现了,它支持颜色图形(例如,每个像素为8位)。除此新功能外,还有一对新的API,SetForegroundColor()SetBackgroundColor(),可让您选择所需的任何颜色。任何询问ApiInformation的应用程序(或库)是否存在这两个新的API 将在OS的版本Y上成功,以及至少Y的MaxVersionTested的任何应用程序都可以成功使用它们。但是由于兼容原因他们无法在仅针对版本X的应用中工作,因为它不知道颜色。他们的图形缓冲区的大小错误,文字可能变得不可见,依此类推。因此,即使OS具有元数据(和实现)来支持它们,API在运行时会在运行时失败。

不幸的是,今天没有很好的处理这种情况,但这是一个相对罕见的事情。它等同于使用LoadLibrary/GetProcAddress(或使用反射的旧版.NET库)的传统Win32库来发现"未来"的API。"

相关内容

最新更新