【问题标题】:Strange type resolution in C# .NET 5 WebAssemblyC# .NET 5 WebAssembly 中的奇怪类型解析
【发布时间】:2021-07-30 06:46:19
【问题描述】:

我有一个 Uno Platform 应用程序,基于 WebAssembly 上的 .NET 5 构建。

我有一个库,每次单击 Toast 通知时都会构造一个 ToastNotificationActivatedEventArgs,并调用 Application.CurrentOnActivated 方法。由于某些原因,该类没有可见的构造函数,无论是通过代码还是通过反射(GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Count() 返回 0)虽然声明了一个 here

所以我使用FormatterServices.GetUninitializedObject 创建了对象,并使用反射初始化了每个字段。然而,在那之后,奇怪的事情开始发生。

protected override void OnActivated(IActivatedEventArgs e)
{
    // Prints True.
    Console.WriteLine(e.GetType() == typeof(ToastNotificationActivatedEventArgs));
    // Gives a valid object.
    var obj1 = (ToastNotificationActivatedEventArgs)e;
    // Prints False.
    Console.WriteLine(e is ToastNotificationActivatedEventArgs);
    // Gives null
    var obj2 = e as ToastNotificationActivatedEventArgs;
}

我怀疑FormatterServices.GetUnitializedObject 一定做错了什么,但是当我尝试使用普通的 .NET 5 复制它时,nothing happened。类型被正常解析。

那么我在这里做错了什么?我知道滥用反射并将FormatterServices 用于反序列化以外的东西并不好,但这是我知道的唯一方法,因为我必须接触一些内部函数才能从外部库复制 UWP 中的行为。

【问题讨论】:

  • 我认为构造函数根本不存在,因为它没有在任何地方使用并且它是内部的,因此链接器将其删除。但是 - 我很好奇 - 外部库如何调用 OnActivated 方法?您是否可以创建一个实现 IActivatedEventArgs 的自定义类并改用它?
  • @MartinZikmund 是的,它是内部的,但不保证它不能在任何地方使用,因为据我所知,Uno.UI 有一堆InternalsVisibleTo 属性。关于OnActivated,因为它是protected,外部库无法从代码中调用它:我使用反射来创建EventArgs 的实例并调用OnActivated
  • @MartinZikmund 由于跨平台代码期待Windows.UI.Notifications.ToastActivatedEventArgs,我怀疑自定义类是否可行。即使它起作用了,我仍然不得不打乱反射来打电话给OnActivated
  • BindingFlags.Private 是 BindingFlags.NonPublic 的错字吗(这是您内部需要的)?我想应该是吧?

标签: c# .net-5 webassembly uno-platform


【解决方案1】:

这是由链接器删除未使用的内部构造函数以减小生成的程序集大小引起的。您可以通过在 WASM 项目的 LinkerConfig.xml 文件中添加以下内容来防止这种情况:

<assembly fullname="Uno">
  <type fullname="Windows.ApplicationModel.Activation.ToastNotificationActivatedEventArgs" />
</assembly>

您现在可以确认构造函数可用:

var constructors = typeof(ToastNotificationActivatedEventArgs).GetConstructors(
   BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
Console.WriteLine(constructors.Length);

【讨论】:

  • 谢谢,但我仍然不明白 isas 如何在 .NET 5 WASM 上工作,当使用 GetType 确认两种类型相同并成功时使用经典演员阵容,但在使用 isas 时失败。
猜你喜欢
  • 2020-11-16
  • 2017-07-15
  • 2015-11-05
  • 2012-09-12
  • 1970-01-01
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多