Assembly.LoadFile()でdllを読んで、そのdllの中のクラスでキャストをすると、InvalidCastException がでるときがある【書きかけ】

実験コード

ClassLibrary1.csprojというdllのプロジェクト

dllに作成したクラス。(中身に特に意味はない)

namespace ClassLibrary1;

public class Class1
{
    public static Class1 CreateInstance() => new Class1(); 

    public int Data1;
    public int Data2;
}

winui3のアプリプロジェクト

メイン画面側で、動的に👆のdllを呼んで、その中のクラスのインスタンスを持つようにした。
(「data 」に入れたものが、「ClassLibrary1.Class1」クラスのインスタンス

で、そのインスタンスを、画面(Page)遷移時のパラメータとして、contentFrame.Navigate()の第二引数に渡した。

using Microsoft.UI.Xaml.Media.Animation;
using System;
using System.Reflection;

namespace FileVerUpTool;

public sealed partial class MainWindow : Window
{
    public MainWindow() => this.InitializeComponent();

    private void nvSample_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
    {
        var dll = Assembly.LoadFile(@"C:\git\FileVerUpTool\ClassLibrary1\bin\x64\Debug\net6.0\ClassLibrary1.dll");
        var type = dll.GetType("ClassLibrary1.Class1");
        var obj = Activator.CreateInstance(type);
        var method = type.GetMethod("CreateInstance", BindingFlags.Static | BindingFlags.Public);

        var data = method.Invoke(obj, null);

        if (args.SelectedItemContainer != null)
        {
            if ((string)args.SelectedItemContainer?.Tag == "SamplePage1")
            {
                contentFrame.Navigate(typeof(BlankPage1), (ClassLibrary1.Class1)data, new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
            }
        }
    }
}

で、ページの中のOnNavigatedTo()で、👆で渡したインスタンスを受けるのだが、その際にClassLibrary1.Class1でキャストして受けると、

using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;

namespace FileVerUpTool;

public sealed partial class BlankPage1 : Page
{
    public BlankPage1() => this.InitializeComponent();

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        var a = (ClassLibrary1.Class1)e.Parameter;

    }
}

こんな感じの例外が起きる。

これが、なんでおきるのかさっぱりわからなかった。

原因

ここに書かれていた。

stackoverflow.com

最初、NavigationViewの「Navigate()」メソッドのパラメータが怪しい?とか思ってたが、そこは関係なかった。

対策

Assembly.LoadFile()の代わりに、Assembly.LoadFrom()でdllをロードする。

dllのロード動作

Assembly.LoadFile()使用時の、出力欄のモジュール読み込みメッセージはコレ。

1回目も2回目も、両方「シンボルが読み込まれました」となっている。


Assembly.LoadFrom()使用時の、出力欄のモジュール読み込みメッセージはコレ。

どうやら、LoadFrom()のときは、同じdllを2回目によんだときに、アンロードしている様子。
(LoadFileのときは、アンロードは行われず、「シンボルが読み込まれました」となっている)

参考?

アセンブリの読み込みのベスト プラクティス
1 つのアセンブリを複数のコンテキストに読み込まない
Assembly.LoadFile()は、別のpathに置かれた同じdllを読むけど、
Assembly.LoadFrom()は、それを読まない、と書いてるっぽい。

https://learn.microsoft.com/ja-jp/dotnet/framework/deployment/best-practices-for-assembly-loading#avoid-loading-an-assembly-into-multiple-contexts

Difference between LoadFile and LoadFrom with .NET Assemblies?
👆のMSdocsが何かいてるかわからん!という記事。同意...

https://stackoverflow.com/questions/1477843/difference-between-loadfile-and-loadfrom-with-net-assemblies