想象一下以下设置:
UWP图书馆:
MinVersion:10240
TargetVersion:16299
如果UniversalApiContract Version 5存在,该库会在运行时检查 如果是,它将使用新的NavigationView控件。
UWP App:
MinVersion:10240
TargetVersion:10240
此应用程序引用UWP Library项目
当我在安装了Windows 10版本16299的计算机上运行此应用程序时,会发生以下情况:
UWP库在运行时检查api合约。因为我有最新版本的Windows 10,是的它存在。
然后它尝试创建NavigationView控件,我得到一个TypeLoadException,消息无法找到Windows运行时类型'Windows.UI.Xaml.Controls.NavigationView'。
什么?为什么? ApiInformation类是否不尊重正在运行的应用程序的目标版本?
我可以做些什么来解决这个问题? 我认为ApiInformation是避免这种情况的方法,但显然不是吗?!
这是一个展示错误的Github存储库:
https://github.com/haefele/ApiInformationTargetVersionFail
如果将MyApp项目的目标版本设置为16299,则一切正常。
答案 0 :(得分:3)
[编辑2018年5月29日]
the ApiInformation
type的方法基于磁盘上WinRT元数据的简单查找 - 如果元数据存在,则调用成功。这使得"点亮"新平台上的新功能,而不会增加您的最低版本。但重要的是ApiInformation
对API的实现一无所知:有时它可能会丢失(例如早期" Insider"版本的操作系统)有时它可能不起作用,因为" quirks" (见下面的例子)。由于JIT和.NET Native工具链的工作方式,.NET也有不同的世界观。
这可能会导致问题......
.NET应用程序使用" Union WinMD"这是Windows SDK中存在的所有已知类型(包括扩展SDK)的并集,对应于应用程序的MaxVersionTested
设置。如果您在下层平台上运行该应用,ApiInformation
会告诉您API不存在,但.NET仍然可以基于Union WinMD进行JIT方法并执行一些反射任务。如果您实际尝试调用API(因为您忘记了ApiInformation
检查),您将在运行时获得MissingMethodException
,因为API并不存在。
如果在较低版本的应用程序中包含较高版本的.NET库,然后尝试在较高版本的操作系统上运行它,则可能会出现另一个问题。在这种情况下,ApiInformation
将成功,因为类型存在于系统元数据中,但.NET将在运行时抛出MissingMethodException
,因为类型在使用的Union WinMD中不存在构建应用程序。
重要提示:这是基于应用的目标版本(又名MaxVersionTested
),而不是库!
如果您构建应用程序的发行版,您甚至会看到.NET Native工具链在“输出”窗口中显示如下警告:
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位的图形缓冲区,或者从不担心文本不可见,因为背景和前景颜色是相同的。一切都好。
现在操作系统版本Y出来了,它支持彩色图形(例如,每像素8位)。除了这个新功能外,还有一对新的API,SetForegroundColor()
和SetBackgroundColor()
,可让您选择所需的颜色。任何询问ApiInformation
这两个新API是否存在的应用程序(或库)将在操作系统的版本Y上成功,并且任何MaxVersionTested
至少为Y的应用程序都可以成功使用它们。但出于兼容性原因,它们无法在仅针对版本X的应用中运行,因为它不知道颜色存在。他们的图形缓冲区大小错误,文本可能变得不可见,依此类推。因此,当在X目标应用程序中使用时,API将在运行时失败,即使操作系统具有支持它们的元数据(和实现)。
不幸的是,今天没有办法处理这种情况,但这种情况相对罕见。它相当于使用LoadLibrary
/ GetProcAddress
(或使用反射的传统.NET库)的遗留Win32库来发现未来的API。"