C
C#2w ago
peppy

Type identity mismatches in plugin framework when plugins depend on one another

In a plugin framework, suppose that one plugin has a dependency on another. As per https://learn.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support, I've given every plugin its own AssemblyLoadContext, while the shared 'core' library is loaded into AssemblyLoadContext.Default. This has worked fine to avoid type identity mismatches on types of the core library. However, I've run into a different source of issues. I instantiate plugins as follows:
PluginLoadContext dll_load_ctx = new PluginLoadContext(dll_path);
Assembly dll = dll_load_ctx.LoadFromAssemblyPath(dll_path);

foreach (Type type in dll.GetExportedTypes()) {
PluginLoadAttribute? load_attr = type.GetCustomAttribute<PluginLoadAttribute>();
if (load_attr == null) continue;

BasePlugin module = Activator.CreateInstance(type) as BasePlugin ?? throw(...)
}
PluginLoadContext dll_load_ctx = new PluginLoadContext(dll_path);
Assembly dll = dll_load_ctx.LoadFromAssemblyPath(dll_path);

foreach (Type type in dll.GetExportedTypes()) {
PluginLoadAttribute? load_attr = type.GetCustomAttribute<PluginLoadAttribute>();
if (load_attr == null) continue;

BasePlugin module = Activator.CreateInstance(type) as BasePlugin ?? throw(...)
}
then store them in a class in the shared core library that exposes a method:
public class PluginStore {
private List<BasePlugin> _plugins;

public TPlugin? get_plugin<TPlugin>() where TPlugin : BasePlugin {
foreach (var plugin in _plugins) {
if (plugin is TPlugin t) return t;
}
return null;
}
}
public class PluginStore {
private List<BasePlugin> _plugins;

public TPlugin? get_plugin<TPlugin>() where TPlugin : BasePlugin {
foreach (var plugin in _plugins) {
if (plugin is TPlugin t) return t;
}
return null;
}
}
The end result is that a plugin that is a dependency of another plugin is loaded, effectively, twice: - the first time in its own PluginLoadContext - a second time as a dependency of another plugin, in that plugin's PluginLoadContext and thus get_plugin routinely fails with a type identity mismatch. How does one properly handle this situation? The intention is that: - plugins are instantiated once by the 'core' - those instances are retrieved at runtime by other plugins, if need be
1 Reply
peppy
peppyOP2w ago
I see. When probing you can return a reference to an Assembly loaded in a different AssemblyLoadContext and that triggers sharing. This solves the issue.

Did you find this page helpful?