trungnt2910
trungnt2910

Reputation: 342

Strange type resolution in C# .NET 5 WebAssembly

I have a Uno Platform app, built on the .NET 5 on WebAssembly.

I have a library, that constructs a ToastNotificationActivatedEventArgs every time a Toast Notification is clicked, and calls the OnActivated method of Application.Current. For some reasons, the class has no constructors visible, both through code, and through Reflection (GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Count() returns 0) although one is declared here.

So I created the object using FormatterServices.GetUninitializedObject, and initialized each fields using reflection. However, after that strange things start to happen.

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;
}

I suspect that FormatterServices.GetUnitializedObject must be doing something bad, but when I tried to replicate that using normal .NET 5, nothing happened. The types are resolved normally.

So what am I doing wrong here? I know that abusing reflection and using FormatterServices for stuff other than deserialization is not nice, but this is the only way I know as I have to touch some internal functions to replicate the behavior in UWP from an external library.

Upvotes: 0

Views: 129

Answers (1)

Martin Zikmund
Martin Zikmund

Reputation: 39082

This is caused by the linker removing the unused internal constructor to decrease the resulting assembly size. You can prevent this by adding the following in the LinkerConfig.xml file in the WASM project:

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

You can now confirm that the constructor is available:

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

Upvotes: 1

Related Questions