COM登録したDLLだから、app.configを使いたくないんだ[assemblyBinding編]

今、Microsoft.Data.SQLiteが私の中でアツい。
ので、使ってみた。
exe形式で動作検証も行い、DLLをCOM登録して、VBA側から使ってみた。
ら、使えなかった!

なお、検証環境はWindows 11 22H2 × Microsoft365 64bit です。
SqliteConnectionインスタンス生成時にエラーになります。

System.TypeInitializationException: 'Microsoft.Data.Sqlite.SqliteConnection' のタイプ初期化子が例外をスローしました。 ---> System.IO.FileNotFoundException: ファイルまたはアセンブリ 'SQLitePCLRaw.core, Version=2.1.2.1721, Culture=neutral, PublicKeyToken=1488e028ca7ab535'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
   場所 Microsoft.Data.Sqlite.SqliteConnection..cctor()

exe形式の場合なら、app.Configに書いてあるassemblyBindingタグの効果が得られないためです。

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  <dependentAssembly>
    <assemblyIdentity name="SQLitePCLRaw.core" publicKeyToken="1488e028ca7ab535" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-2.1.4.1835" newVersion="2.1.4.1835" />
  </dependentAssembly>
</assemblyBinding>
</runtime>

VBAから使用する場合、使用者はあくまでEXCEL.exeですしね。
dllのプロジェクト配下にもapp.configができていると思うけど、なんの役にも立たぬわ!
何かしてくれるのかと期待するじゃないか。
紛らわしいので、シリアル化アセンブリの生成機能を切っとく!

さて、dllとして公開するクラスのコンストラクタで、リダイレクトするための仕組みをいれておきます。
こちらこちらを参考にさせていただきました、というか丸パクリです。

/// <summary>
/// 公開するクラスのコンストラクタ
/// </summary>
public hogehoge()
{
    RedirectAssembly("SQLitePCLRaw.core", new Version(2, 1, 4, 1835), "1488e028ca7ab535");
}

public static void RedirectAssembly(string shortName, Version targetVersion, string publicKeyToken)
{
    ResolveEventHandler handler = null;

    handler = (sender, args) => {
        var requestedAssembly = new AssemblyName(args.Name);
        if (requestedAssembly.Name != shortName)
            return null;

        if (requestedAssembly.Version > targetVersion)
        {
            return null;
        }
        requestedAssembly.Version = targetVersion;
        requestedAssembly.SetPublicKeyToken(new AssemblyName($"x, PublicKeyToken={publicKeyToken}").GetPublicKeyToken());
        requestedAssembly.CultureInfo = System.Globalization.CultureInfo.InvariantCulture;

        AppDomain.CurrentDomain.AssemblyResolve -= handler;

        return Assembly.Load(requestedAssembly);
    };
    AppDomain.CurrentDomain.AssemblyResolve += handler;
}

NuGetで更新したら、ココのバージョン番号を毎回直さないといけないのかなぁ…?
てかインストールしたのは2.1.4.1835なんですけど、配置先では1721で探してるの、なんで?
……誰かこのあたりの仕組みのことを教えてください。

でも、これでインスタンス生成時にhandlerの内容が実行されて、エラーが出なくなります。


他にもニッチなIT関連要素をまとめていますので、よければ一覧記事もご覧ください。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)