NuGet依赖加载器
适配版本:4.1.1(其余版本尚未检测兼容性且无检测计划)
主要功能:
DependencyLoaderMod 是一个 SPT 服务端模组的”依赖加载器”,解决了 SPT 4.0 服务端无法自动加载模组依赖 DLL(尤其是 NuGet 包)的限制。核心职责有两个:
1. 运行时程序集解析(核心)
– 在 [DependencyLoaderMod.cs]中注册全局 `AppDomain.AssemblyResolve` 事件,从各模组注册的 `dependencies/` 目录里加载依赖 DLL(含原生库 `e_sqlite3.dll` 这类通过 `NativeLibrary.SetDllImportResolver` 解析的文件)。
– 因为 SPT 的 DI 扫描器会调用 `assembly.GetTypes()`,一旦某个模组类型引用了外部 DLL,就必须先能解析这些 DLL,否则启动即崩。这个 mod 就是提前挂好”钩子”。
2. NuGet 自动回退下载
– 当模组的 `dependencies/` 目录缺失或不全时,通过解析该模组的 `*.deps.json`([AutoResolveFromDepsJsonAsync]自动从国内镜像源(Azure 中国、华为云、腾讯云、清华 TUNA、博客园,最后官方源兜底)下载缺失的 NuGet 包并解压 DLL。
– 配置在 [config.json]:`enableNugetFallback`、`nugetSource`(留空=自动检测)、`enableProgressBar`。
提供的 API:
所有 API 都在静态类 `DependencyLoaderMod.Services.DependencyLoadService`内
| 方法 | 用途 |
|—|—|
| `AddResolveDirectory(path)` | 注册一个托管 DLL 解析目录,AssemblyResolve 时按注册顺序搜索 |
| `AddNativeResolve(assemblyName, nativeDllName, nativeDllPath)` | 注册原生库映射,程序集 DllImport 时从指定路径加载 |
| `HasRequiredDlls(path)` | 检查目录是否存在且含至少一个 `.dll` |
| `AutoResolveFromDepsJsonAsync(depsJsonPath, targetDir, sourceUrl=null, showProgress=true)` | 按 deps.json 自动补齐缺失 NuGet 依赖 |
| `DownloadPackageWithProgressAsync(pkg, ver, targetDir, sourceUrl, showProgress)` | 带进度条下载单个包 |
| `DetectNuGetSourceAsync(configuredSource)` | 按区域检测最优 NuGet 源 |
| `CacheDirectory`(属性) | 全局下载缓存目录,默认 `user/cache/DLLCache` |
如何使用
1. 编译期引用(不复制 DLL,运行时由 DependencyLoaderMod 提供):
<ItemGroup>
<Reference Include=”DependencyLoaderMod”>
<HintPath>..\DependencyLoaderMod\obj\Release\DependencyLoaderMod.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
2. 自己的依赖 DLL 构建后移入 `dependencies/`,用 csproj 里的 `MoveDependencies` 目标实现,同时把 `*.deps.json` 保留在根目录供自动解析用。
3. 在插件 `OnLoad()` 里注册依赖:
var depsDir = Path.Combine(modDir, “dependencies”);
// ① 缺失时从 NuGet 自动补齐(可先查缓存目录)
if (!DependencyLoadService.HasRequiredDlls(depsDir))
{
var cacheDir = DependencyLoadService.CacheDirectory; // 默认 user/cache/DLLCache
if (!DependencyLoadService.HasRequiredDlls(cacheDir))
{
await DependencyLoadService.AutoResolveFromDepsJsonAsync(
Path.Combine(modDir, “MyMod.deps.json”), cacheDir);
}
// 从缓存复制到 dependencies/
}
// ② 注册托管 DLL 解析目录
DependencyLoadService.AddResolveDirectory(depsDir);
// ③ 注册原生库(如 SQLite)
DependencyLoadService.AddNativeResolve(
“SQLitePCLRaw.provider.e_sqlite3”, “e_sqlite3”,
Path.Combine(modDir, “runtimes”, “win-x64”, “native”, “e_sqlite3.dll”));
“`
注意事项
– 加载顺序:DependencyLoaderMod 必须在其他模组之前加载(其 `ModMetadata` 静态构造函数在 [DependencyLoaderMod.cs]就提前注册了 `AssemblyResolve`),插件入口标记为 `PreSptModLoader`。所以它是基础设施型模组,其他模组应在 `ModDependencies` 里声明依赖它。
– `dependencies/` 目录:注册解析目录时若目录不存在会被跳过(只打 Warning),所以要先确保依赖就位再 `AddResolveDirectory`。
– NuGet.Protocol.dll 必须留在 mod 根目录(不能进 `dependencies/`),因为 CLR 在静态构造函数运行前就需要加载它。
我不觉得把这个贴子发在语言环境这个板块是一个好主意
隐藏内容需要回复可以看见









666666
666
666
1
6666666
66666666666666666666
666666666
6
6666666666
感谢