為.Net專案新增動態庫載入路徑

六镇2012發表於2024-10-30

為.Net專案新增動態庫載入路徑_51CTO部落格_linux 動態庫載入路徑

本文分別基於.Net Framework和.Net Core的WPF應用程式為例,來說明如何為.Net專案新增自定義動態庫載入路徑。本文基於.Net Core建立WPF時,使用了.Net5作為目標框架。

1、.Net Framework

在基於.Net Framework的WPF專案中,直接在配置檔案(App.config)中新增runtime節點即可。

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <!-- 指定載入程式集時公共語言執行時搜尋的子目錄, 
         其中privatePath是相對於*.exe.config檔案的相對路徑,
         多個資料夾以分號分隔。-->
    <probing privatePath="Libs\Lib1;Libs\Lib2"/>
  </assemblyBinding>
</runtime>

2、.Net5

在基於.Net5的WPF專案中,使用privatePath已經不能夠實現指定資料夾程式集的載入了,這大概時因為在.Net5中,程式集的載入依賴於應用程式的.deps.json檔案,而privatePath指定的資料夾中的程式集不會被新增到.deps.json檔案中。

基於<probing privatePath="..." /> doesn't work in .Net 5.0 · Issue #45342 · dotnet/runtime · GitHub,在專案檔案(配置檔案中應該也可以)設定動態庫載入路徑,然後基於AssemblyLoadContext類的Resolving事件,在應用程式查詢未知型別時載入配置檔案中的動態庫。

(1)在.csproj檔案中設定動態庫路徑

<ItemGroup>
  <RuntimeHostConfigurationOption Include="SubdirectoriesToProbe" Value="Plugins" />
</ItemGroup>

(2)在程式碼中實現型別動態載入

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        //載入程式集事件
        AssemblyLoadContext.Default.Resolving += ResolveAssembly;

        base.OnStartup(e);
    }
    
    //載入指定位置程式集
    private static Assembly ResolveAssembly(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
    {
        var probeSetting = AppContext.GetData("SubdirectoriesToProbe") as string;
        if (string.IsNullOrEmpty(probeSetting))
        {
            return null;
        }

        foreach (var subDirectory in probeSetting.Split(';'))
        {
            var pathMaybe = Path.Combine(AppContext.BaseDirectory, subDirectory, $"{assemblyName.Name}.dll");
            if (File.Exists(pathMaybe))
            {
                return assemblyLoadContext.LoadFromAssemblyPath(pathMaybe);
            }
        }

        return null;
    }
}

相關文章