HomeFeaturesPluginsDocsDownload

Discovery & loading

How a folder on disk becomes a running plugin — and the one detail that explains most loading problems.

At startup

  1. The host resolves plugins/ next to the executable.
  2. For each subfolder, it reads plugin.json. No manifest, no plugin.
  3. It checks the type discriminator and whether hostApiVersion falls inside the range this host supports. Out of range, the plugin is skipped rather than half-loaded.
  4. It loads the entryAssembly into a fresh, isolated load context, resolved against that plugin's own .deps.json — which is why every plugin can carry its own driver version without colliding with any other.
  5. It reflects for the type the plugin type expects (IDbProvider, IToolPlugin, and so on) and activates it. A tool assembly may ship several tools; all are instantiated.
  6. It scans the loaded plugin for the optional capabilities — settings panes and keyboard shortcuts register themselves at this point.

Loading never throws back at the host: a failure is captured per plugin and logged, so one broken plugin can't take the app down with it.

Isolation, and the one exception

Each plugin gets its own AssemblyLoadContext. Two plugins can therefore depend on different, incompatible versions of the same driver and neither will notice the other.

The exception that matters. The load context deliberately declines to resolve SqlExplorer.Sdk itself, falling back to the host's copy — so IDbProvider keeps a single type identity across the boundary. That is precisely why every plugin project sets Private="false" on the SDK reference: SqlExplorer.Sdk.dll must not be copied into the plugin's own folder.

If a plugin loads but the host says it doesn't implement the interface it obviously implements, this is almost always the cause: two copies of the SDK, two distinct types with the same name.

What ships in the folder

plugins/ myengine/ plugin.json // the manifest SqlExplorer.Providers.MyEngine.dll // entryAssembly SqlExplorer.Providers.MyEngine.deps.json // how the driver gets resolved MyEngine.Driver.dll ... the rest of the build output, but NOT SqlExplorer.Sdk.dll

Set CopyLocalLockFileAssemblies so the full private dependency closure lands in the folder, and keep the .deps.json — without it the load context has nothing to resolve your driver against.