Sworld

Sworld

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

AvaloniaがAOTコンパイル後に実行できない解決策

問題の発見#

最近、Avalonia プログラムを作成している際に、デバッグ時は正常に動作するのに、リリース後は実行できないことに気づき、非常に奇妙に感じました。私のリリース設定には以下の 2 つがあります:

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

最初の行はトリミングを有効にし、2 番目の行は AOT コンパイルを有効にしています(ただし、開発時には AOT が有効になっていません。プレビューウィンドウが AOT をサポートしていないためです)。

いくつかの調査の結果、これら 2 つに問題があることがわかりました:

  1. 反射は AOT に対して不利です。私のViewLocator.csはオブジェクトを作成するために反射を使用しています。
  2. 一部のライブラリはトリミングのサポートが不十分であるため、トリミングを無効にする必要があります。

解決策#

問題 1: 反射の排除#

元のコードは反射を使用してオブジェクトを作成していました:

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)!; // ここで反射を使用
        }
        return new TextBlock { Text = "Not Found: " + viewModelType.FullName };
    }
    return null;
}

修正後はファクトリメソッドを使用します:

public Control? Build(object? param)
{
    if (param != null && param is ViewModelBase)
    {
        var viewModelType = param.GetType();
        if (_viewModelViewMappings.TryGetValue(viewModelType, out var viewFactory))
        {
            return viewFactory(); // ファクトリメソッドを使用
        }
        return new TextBlock { Text = "Not Found: " + viewModelType.FullName };
    }
    return null;
}

これにより、反射を排除できます。

問題 2: 特定のライブラリのトリミングを無効にする#

リリース時に、多くのトリミング警告に気づきました。

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.

そのため、プロジェクトの sln ファイルを修正し、以下のスニペットを追加して、外部の xml ファイルを通じてトリミングを制限しました。

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

以下は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>

私はすべての警告が出たプロジェクトを追加しましたが、その後のコンパイルでも新しい警告が出続けました。しかし、プログラムは正常に実行できるようになりました。これで、すべての問題が解決しました。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。