UWP开发之Mvvmlight实践六:MissingMetadataException解决办法(.Net Native下Default.rd.xml配置问题)

最近完成一款UWP应用,在手机端测试发布版(Release)的时候应用莫名奇妙的强行关闭,而同样的应用包在PC端一点问题都没有,而且Debug版在两个平台都没有问题,唯独手机的Release版有问题。实在没办法只能记录每个步骤的Log,通过查看Log发现是SuspensionManager的DataContractSerializer序列化抛出了ArgumentNullException异常。

常见.NET Native引发异常:

例1:

System.InvalidCastException: InvalidCast_Com
at SharedLibrary!<BaseAddress>+0x429e9d 
例2:
HResult : -2146233088 TypeName : Newtonsoft.Json.JsonException, Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed Message : Newtonsoft.Json.JsonException: Error creating ‘NestedObjectJsonConverter‘. ---> System.NullReferenceException: Object reference not set to an instance of an object. at Newtonsoft.Json.Serialization.JsonTypeReflector.<>c.b__18_1(Object param) at
例3:
Exception thrown: ‘System.AggregateException‘ in System.Private.Threading.dll
Exception thrown: ‘System.ArgumentException‘ in System.Linq.Expressions.dll
Exception thrown: ‘System.ArgumentException‘ in System.Linq.Expressions.dll
Exception thrown: ‘System.ArgumentException‘ in System.Linq.Expressions.dll
The thread 0x2a30 has exited with code 0 (0x0).
Exception thrown: ‘System.Reflection.MissingMetadataException‘ in System.Private.Reflection.Core.dll
Additional information: ‘Microsoft.Extensions.Caching.Memory.MemoryCacheOptions‘ is missing
 
原因:
因为手机Release版使用了.Net Native编译。.Net Native编译时将源代码转换为本机代码不再有中间语言(IL)。这也是为什么.NET Native编译的代码中发生的异常不会出现在 JIT 编译的代码中。
 
.NET Native编译做了下面几件事:
    详细介绍参照MSDN:https://msdn.microsoft.com/zh-cn/library/dn807190(v=vs.110).aspx
  • 对于某些代码路径,它将依靠反射和元数据的代码替换为静态本机代码。

  • 如果可能,它会尝试消除所有元数据。
  • 它只将实际由应用程序调用的实现代码包含在最终应用程序集中。这尤其会对第三方库和 .NET Framework 类库中的代码产生影响。因此,应用程序不再依赖第三方库或完整的 .NET Framework 类库;相反,对应用程序而言,当前第三方和 .NET Framework 类库中的代码都是本地的。
  • 它将完整的 CLR 替换为主要包含垃圾回收器的重构运行时。重构运行时位于应用程序中名为 mrt100_app.dll 本地库,且其大小仅为几百千字节。这可能是因为静态链接不再需要公共语言运行时执行多个服务。

常见问题操作:

因为 .NET Native只在获知应用程序实际调用了实现代码时才会将它链接到应用程序中,所以应用程序中可能不包含以下操作中所需的元数据或实现代码。如果在运行时缺少必需的元数据或实现代码,应用程序运行时将引发MissingMetadataExceptionMissingRuntimeArtifactExceptionMissingInteropDataException 异常。

  • 反射。

  • 动态或后期绑定调用。
  • 序列化和反序列化。
  • COM 互操作。

解决办法:

为了让.NET Native编译时不删除我们需要的元数据或者实现代码,这时需要配置Default.rd.xml(运行时指令)文件,指定程序需要的元数据。

文件地址如下图:

默认的配置为:

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
  <Application>
    <!--
      An Assembly element with Name="*Application*" applies to all assemblies in
      the application package. The asterisks are not wildcards.
    -->
    <Assembly Name="*Application*" Dynamic="Required All"/>

    <!-- Add your application specific runtime directives here. -->

  </Application>
</Directives>

为了能正确配置建议使用这个工具:MissingMetadataException troubleshooterhttp://dotnet.github.io/native/troubleshooter/type.html#

比如配置SuspensionManager挂起中断处理(DataContractSerializer序列化)

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
  <Application>
    <!--
      An Assembly element with Name="*Application*" applies to all assemblies in
      the application package. The asterisks are not wildcards.
    -->
    <Assembly Name="*Application*" Dynamic="Required All"/>

    <Type Name="TestDemo.StudentModel" DataContractSerializer="Required Public" />

  </Application>
</Directives>

MSDN介绍配置

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
  <Namespace Name="Contoso.Cloud.AppServices" Serialize="Required Public" />
  <Namespace Name="ContosoClient.ViewModels" Serialize="Required Public" />
  <Namespace Name="ContosoClient.DataModel" Serialize="Required Public" />
  <Namespace Name="Contoso.Reader.UtilityLib" Serialize="Required Public" />

  <Namespace Name="System.Collections.ObjectModel" >
    <TypeInstantiation Name="ObservableCollection"
          Arguments="ContosoClient.DataModel.ProductItem" Serialize="Public" />
    <TypeInstantiation Name="ReadOnlyObservableCollection"
          Arguments="ContosoClient.DataModel.ProductGroup" Serialize="Public" />
  </Namespace>
</Application>
</Directives>

详细节点介绍与配置参照MSDN:运行时指令 (rd.xml) 配置 https://msdn.microsoft.com/zh-cn/library/dn600639(v=vs.110).aspx

注意点:

DataContractSerializerDataContractJsonSerializerXmlSerializer 类有些特殊,有些情况需要配置有些情况不需要配置Default.rd.xml文件。
 
不需要配置情况:(构造函数中使用TypeOf指定类型时.Net Native编译器会自动处理)
DataContractSerializer dataSer = new DataContractSerializer(typeof(T));

需要配置情况:(构造函数外部使用Typeof指定类型时必须在Default.rd.xml文件配置)

Type t = typeof(DataSet); 

XmlSerializer ser = new XmlSerializer(t);

或者SuspensionManager挂起中断处理的

DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary<string, object>), _knownTypes);

或者

XmlSerializer xSerializer = new XmlSerializer(typeof(Teacher),
                            new Type[] { typeof(Student),
                                         typeof(Course),
                                         typeof(Location) });

备注:

将 Windows 应用商店应用迁移到 .NET Native建议仔细阅读MSDN说明(https://msdn.microsoft.com/zh-cn/library/dn600634(v=vs.110).aspx)。

时间: 2024-10-20 07:29:51

UWP开发之Mvvmlight实践六:MissingMetadataException解决办法(.Net Native下Default.rd.xml配置问题)的相关文章

UWP开发之Mvvmlight实践七:寻找Mobile模拟器或者实体机中Packages文件夹小技巧

在开发中或者后期测试乃至最后交付使用的时候,如果应用出问题了我们一般的做法就是查看Log文件.上章也提到了查看Log文件,这章重点讲解下如何查看Log文件?如何找到我们需要的Packages安装包目录? 桌面系统应用 安装在桌面系统上的应用,我们是很容易就可以找到安装包的目录. 目录结构:C:\Users\{用户名}\AppData\Local\Packages\{UWP应用包名}\ {用户名}=系统登录用户名,{UWP应用包名}=UWP应用打包时的名称. 比如查看[UWP开发之Mvvmligh

UWP开发之Mvvmlight实践五:SuspensionManager中断挂起以及复原处理

最近比较忙有一段时间没有更新了,再接再厉继续分享. 先我们看看App在生命周期中会出现那些状态: 详细介绍参考官网:App lifecycle  https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/app-lifecycle 一般情况: 比如用新闻APP看新闻的时候突然收到邮件,然后跳转到邮件APP查看邮件,查看完了再回到APP继续看新闻. 这个时候如果不做中断挂起处理的话,是很难保证APP会恢复到跳转之前的状态.之所以说很难保证

UWP开发之Mvvmlight实践九:基于MVVM的项目架构分享

在前几章介绍了不少MVVM以及Mvvmlight实例,那实际企业开发中将以那种架构开发比较好?怎样分层开发才能节省成本? 本文特别分享实际企业项目开发中使用过的项目架构,欢迎参照使用!有不好的地方欢迎指点! 基于MVVM的UWP项目架构 每个项目或者目录下需要什么文件如下图所示: 项目参照关系: 备注:如果使用Entity Framework Core做ORM持久层,只需要将UA.DataAccess层做替换就可以.希望本文能对您的团队开发带来一定功效.

UWP开发之Mvvmlight实践四:{x:bind}和{Binding}区别详解

{x:bind}是随着UWP被推出而被添加的,可以说是Win10 UWP开发专有扩展.虽然 {x:Bind} 缺少{Binding} 中的一些功能,但它运行时所花费的时间和使用的内存量均比 {Binding} 要少,且支持更好的调试. 参照网址:{x:Bind} 标记扩展,GitHub微软UWP实例之XamlBind 1,{x:Bind} 基本原理 在 XAML 加载时,{x:Bind} 将转换为你所需的绑定对象,此对象将从数据源上的某一属性中获取相关值.绑定对象可以配置为观察数据源属性值的更改

UWP开发之Template10实践二:拍照功能你合理使用了吗?(TempState临时目录问题)

最近在忙Asp.Net MVC开发一直没空更新UWP这块,不过有时间的话还是需要将自己的经验和大家分享下,以求共同进步. 在上章[UWP开发之Template10实践:本地文件与照相机文件操作的MVVM实例(图文付原代码)]已经谈到了使用FileOpenPicker进行文件选择,以及CameraCaptureUI进行拍照. 对于文件选择一般进行如下设置就能实现: // 选择多个文件 FileOpenPicker openPicker = new FileOpenPicker(); openPic

UWP开发之ORM实践:如何使用Entity Framework Core做SQLite数据持久层?

选择SQLite的理由 在做UWP开发的时候我们首选的本地数据库一般都是Sqlite,我以前也不知道为啥?后来仔细研究了一下也是有原因的: 1,微软做的UWP应用大部分也是用Sqlite.或者说是微软推荐使用Sqlite吧! 2,简单!就只有一个类库没有多余的参照什么的.不像其他数据库还得做复杂配置什么的麻烦! 3,不需要数据库服务,数据服务和客户都在同一个进程里面.如下图: 4,作为存储系统它只支持一个用户一个数据实体. 5,跨平台跨结构,这个好! Sqlite主要使用内容 如果想充分使用好S

win10开始菜单打不开怎么办 win菜单键没反应解决办法

win10开始菜单打不开怎么办 win菜单键没反应解决办法 —————————————————————————————————————————————————————————————————————————— 1.右键点击任务栏—— 任务管理器,点击文件——运行新任务,新建任务 “powershell”同时勾选下方的“以管理员身份运行” .确定. 2.在弹出“管理员”运行中输入:Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -Disab

Mac终端打不开或显示 [进程已完成]解决办法

前两天在弄freeSwitch,由于不是很熟悉,中间可能有操作错误的地方.结果导致第二天终端打开的时候一闪就消失了.由于当时手头上临时有比较急的活,也没怎么在意,结果今天需要重新搞freeSwitch死活打不开终端了. 之后再终端上右键选择使用设置新建窗口上新建了一个和当前不同样式的终端,发现不是一闪就消失了,但是出现的是 [进程已完成].也无法进行操作. 然后尝试了几种方法,包括: 1.用磁盘工具->急救->验证磁盘权限->修复磁盘权限: 2.在终端偏好设置->描述文件->

iOS开发之oc(六)--点语法

(一)点语法 1.利用点语法替代set方法和get方法 方法调用 Student *stu = [Student new]; [stu setAge:100]; int age = [stu age]; 点语法 stu.age = 100; int age = stu.age; 2.点语法的本质 >其实点语法的本质还是方法调用 >当使用点语法时,编译器会自动展开成相应的方法(编译器特性) 3.注意 死循环注意 - (void) setAge:(int)age { // 下面的代码会引发死循环