diff --git a/SfeduSchedule/PluginLoader.cs b/SfeduSchedule/PluginLoader.cs index 98f3328..7073513 100644 --- a/SfeduSchedule/PluginLoader.cs +++ b/SfeduSchedule/PluginLoader.cs @@ -46,11 +46,20 @@ public static class PluginLoader public sealed class PluginLoadContext(string pluginMainAssemblyPath) : AssemblyLoadContext(true) { private readonly AssemblyDependencyResolver _resolver = new(pluginMainAssemblyPath); + private static readonly HashSet SharedAssemblyNames = + [ + typeof(IPlugin).Assembly.GetName().Name!, + typeof(PluginLoader).Assembly.GetName().Name! + ]; - // Разрешаем управляемые зависимости плагина из его папки. - // Возвращаем null, чтобы отдать решение в Default ALC для общих сборок (например, ModeusSchedule.Abstractions). + // Контракт плагина и API хоста должны иметь одинаковую идентичность типов в обоих контекстах загрузки. + // Поэтому их всегда берём из Default ALC, даже если копии DLL лежат рядом с плагином. protected override Assembly? Load(AssemblyName assemblyName) { + if (assemblyName.Name != null && SharedAssemblyNames.Contains(assemblyName.Name)) + return null; + + // Остальные управляемые зависимости разрешаем из папки плагина. var path = _resolver.ResolveAssemblyToPath(assemblyName); return path is null ? null : LoadFromAssemblyPath(path); } @@ -61,4 +70,4 @@ public sealed class PluginLoadContext(string pluginMainAssemblyPath) : AssemblyL var path = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); return path is null ? IntPtr.Zero : LoadUnmanagedDllFromPath(path); } -} \ No newline at end of file +}