Sworld

Sworld

The only way to do great work is to love what you do.

Solution for Avalonia not running after AOT compilation

Problem Discovery#

Recently, while developing an Avalonia application, I found that it ran normally during debugging but could not run after publishing, which felt strange. My publish configuration included the following two lines:

    <PublishTrimmed>True</PublishTrimmed>
    <PublishAot Condition="'$(Configuration)' != 'Debug'">true</PublishAot>

The first line enabled trimming, and the second line enabled AOT compilation (but it was not enabled during development because the preview window does not support AOT).

After some investigation, I discovered that both had issues:

  1. Reflection is not friendly to AOT; my ViewLocator.cs used reflection to create objects.
  2. Some libraries do not support trimming well, so trimming needs to be disabled for them.

Solution#

Issue 1: Eliminate Reflection#

The original code used reflection to create objects:

public Control? Build(object? param)
{
    if (param != null && param is ViewModelBase)
    {
        var viewModelType = param.GetType();
        if (_viewModelViewMappings.TryGetValue(viewModelType, out var viewType))
        {
            return (Control)Activator.CreateInstance(viewType)!; // Reflection used here
        }
        return new TextBlock { Text = "Not Found: " + viewModelType.FullName };
    }
    return null;
}

After modification, it used a factory method:

public Control? Build(object? param)
{
    if (param != null && param is ViewModelBase)
    {
        var viewModelType = param.GetType();
        if (_viewModelViewMappings.TryGetValue(viewModelType, out var viewFactory))
        {
            return viewFactory(); // Factory method used
        }
        return new TextBlock { Text = "Not Found: " + viewModelType.FullName };
    }
    return null;
}

This eliminates the use of reflection.

Issue 2: Disable Trimming for Specific Libraries#

During publishing, I noticed many trimming warnings like these:

2>Assembly 'Serilog' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries
2>Assembly 'ReactiveUI' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries
2>Assembly 'SukiUI' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries
2>Assembly 'Avalonia.Controls.DataGrid' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries
2>Assembly 'Avalonia.Controls.DataGrid' produced AOT analysis warnings.

Therefore, I modified the project's sln file to add the following snippet, using an external XML file to limit trimming:

  <ItemGroup>
    <TrimmerRootDescriptor Include="TrimmerRoots.xml" />
  </ItemGroup>

Below is the content of TrimmerRoots.xml:

<?xml version="1.0" encoding="utf-8" ?>
<linker>
  <assembly fullname="Serilog" />
  <assembly fullname="Serilog.Sinks.Console" />
  <assembly fullname="Serilog.Sinks.File" />
  <assembly fullname="ReactiveUI" />
  <assembly fullname="SukiUI" />
  <assembly fullname="Serilog.Sinks.File" />
</linker>

I included all the projects that had warnings, and although there were still new warnings during subsequent compilations, the application could run normally. Thus, all issues were resolved.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.