API Reference
Overview
This document provides a comprehensive API reference for the QuantumKat Plugin SDK. It covers all public interfaces, classes, and methods available for plugin development.
Core Namespace: QuantumKat.PluginSDK.Core
Interfaces
IPlugin
public interface IPlugin
{
string Name { get; }
string Description { get; }
string Version { get; }
string Author { get; }
Dictionary<string, List<string>> PluginDependencies { get; }
void Initialize(PluginBootstrapContext context);
void RegisterServices(IServiceCollection services);
}
Properties:
Name: Unique plugin identifierDescription: Brief plugin descriptionVersion: Plugin version (semantic versioning recommended)Author: Plugin author namePluginDependencies: Dictionary of plugin dependencies with version constraints
Methods:
Initialize(PluginBootstrapContext): Called during plugin initializationRegisterServices(IServiceCollection): Register plugin services with DI container
IThreadedPlugin
public interface IThreadedPlugin : IPlugin
{
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
}
Methods:
StartAsync(CancellationToken): Start plugin background operationsStopAsync(CancellationToken): Stop plugin background operations gracefully
IPluginEventRegistry
public interface IPluginEventRegistry
{
void SubscribeToMessage(string name, Func<IMessage, Task<bool>> predicate, Func<IMessage, Task> handler);
void UnsubscribeFromMessage(string name);
void ClearAllSubscriptions();
bool IsSubscribed(string name);
Dictionary<string, (Func<IMessage, Task<bool>> predicate, Func<IMessage, Task> handler)> GetSubscriptions();
}
Methods:
SubscribeToMessage(string, Func<IMessage, Task<bool>>, Func<IMessage, Task>): Register named message event handler with async predicate filterUnsubscribeFromMessage(string): Unregister a specific handler by nameClearAllSubscriptions(): Clear all handlers registered by the calling pluginIsSubscribed(string): Check if a subscription exists by nameGetSubscriptions(): Get all subscriptions registered by the calling plugin
IPluginServiceProvider
public interface IPluginServiceProvider
{
IServiceProvider ServiceProvider { get; }
void RebuildServiceProvider();
void RegisterServicesAndRebuild(Action<IServiceCollection> serviceRegistration);
}
Properties:
ServiceProvider: Current shared service provider instance
Methods:
RebuildServiceProvider(): Rebuild service provider with current servicesRegisterServicesAndRebuild(Action<IServiceCollection>): Register services and rebuild
Classes
PluginManager
public class PluginManager : IPluginManager
{
public PluginManager(IPluginServiceProvider sharedServiceProvider, IConfiguration configuration, ILogger logger);
public List<IPlugin> LoadedPlugins { get; }
public void LoadPlugins(IEnumerable<string> pluginPaths, bool throwOnError = true);
public void RegisterAllPluginServices();
public async Task StartAllPluginsAsync(CancellationToken cancellationToken);
public async Task StopAllPluginsAsync(CancellationToken cancellationToken);
public async Task StartPluginAsync(IThreadedPlugin plugin, CancellationToken cancellationToken);
public async Task StopPluginAsync(IThreadedPlugin plugin, CancellationToken cancellationToken);
public async Task DispatchMessageAsync(IMessage message);
}
Constructor Parameters:
sharedServiceProvider: Shared service provider for DI managementconfiguration: Application configurationlogger: Logger instance
Properties:
LoadedPlugins: List of all loaded plugins
Methods:
LoadPlugins(IEnumerable<string>, bool): Load plugins from assembly pathsRegisterAllPluginServices(): Register all plugin servicesStartAllPluginsAsync(CancellationToken): Start all threaded pluginsStopAllPluginsAsync(CancellationToken): Stop all threaded pluginsStartPluginAsync(IThreadedPlugin, CancellationToken): Start specific pluginStopPluginAsync(IThreadedPlugin, CancellationToken): Stop specific pluginDispatchMessageAsync(IMessage): Dispatch message to all registered handlers
PluginBootstrapContext
public class PluginBootstrapContext
{
public required IConfiguration Configuration { get; init; }
public required ILogger Logger { get; init; }
public required IServiceProvider CoreServices { get; init; }
public required string PluginDirectory { get; init; }
public IPluginEventRegistry? EventRegistry { get; init; }
public IPluginServiceProvider? SharedServiceProvider { get; init; }
}
Properties:
Configuration: Application configurationLogger: Logger instance for plugin useCoreServices: Core application servicesPluginDirectory: Directory containing the pluginEventRegistry: Event registry for message handling (optional)SharedServiceProvider: Shared service provider for dynamic registration (optional)
SharedServiceProvider
public class SharedServiceProvider : IPluginServiceProvider, IDisposable
{
public SharedServiceProvider(IServiceCollection serviceCollection);
public IServiceProvider ServiceProvider { get; }
public void RebuildServiceProvider();
public void RegisterServicesAndRebuild(Action<IServiceCollection> serviceRegistration);
public void Dispose();
}
Constructor Parameters:
serviceCollection: Service collection to build provider from
PluginEventRegistry
public class PluginEventRegistry : IPluginEventRegistry
{
public void SubscribeToMessage(string name, Func<IMessage, Task<bool>> predicate, Func<IMessage, Task> handler);
public void UnsubscribeFromMessage(string name);
public void ClearAllSubscriptions();
public bool IsSubscribed(string name);
public Dictionary<string, (Func<IMessage, Task<bool>> predicate, Func<IMessage, Task> handler)> GetSubscriptions();
public async Task DispatchMessageAsync(IMessage message);
}
PluginLoadContext
public class PluginLoadContext : AssemblyLoadContext
{
public PluginLoadContext(string pluginPath);
protected override Assembly Load(AssemblyName assemblyName);
}
Constructor Parameters:
pluginPath: Path to the plugin assembly
Extensions Namespace: QuantumKat.PluginSDK.Core.Extensions
ServiceCollectionExtensions
public static class ServiceCollectionExtensions
{
public static PluginSDKBuilder AddPluginSDK(this IServiceCollection services, IConfiguration configuration, ILogger logger);
}
Extension Methods:
AddPluginSDK(IServiceCollection, IConfiguration, ILogger): Add Plugin SDK services
PluginSDKBuilder
public class PluginSDKBuilder
{
public IPluginServiceProvider SharedServiceProvider { get; }
public PluginSDKBuilder LoadPlugins(IEnumerable<string> pluginPaths);
public PluginSDKBuilder ConfigureServices(Action<IServiceCollection> configureServices);
public IServiceProvider Build();
}
Properties:
SharedServiceProvider: Access to shared service provider
Methods:
LoadPlugins(IEnumerable<string>): Load plugins and register servicesConfigureServices(Action<IServiceCollection>): Configure additional servicesBuild(): Build final service provider
Settings Namespace: QuantumKat.PluginSDK.Settings
ISetting
public interface ISetting
{
// Marker interface for settings classes
}
SettingsManager
public class SettingsManager
{
public SettingsManager(string file);
public IConfiguration GetConfiguration<T>() where T : new();
public void Save(object settings);
public static T InitializeSettings<T>() where T : new();
}
Constructor Parameters:
file: Settings file name/path
Methods:
GetConfiguration<T>(): Get configuration with automatic file creationSave(object): Save settings to fileInitializeSettings<T>(): Initialize settings with default values
Attributes Namespace: QuantumKat.PluginSDK.Attributes
SettingCallbackAttribute
[AttributeUsage(AttributeTargets.Method)]
public class SettingCallbackAttribute : Attribute
{
// Marker attribute for callback methods
}
Usage: Applied to methods that should be called when settings are initialized.
Discord Extensions Namespace: QuantumKat.PluginSDK.Discord.Extensions
SocketMessageExtensions
public static class SocketMessageExtensions
{
public static bool IsUserMessage(this SocketMessage socketMessage, out SocketUserMessage userMessage);
public static bool IsFromBot(this SocketMessage socketMessage);
}
Extension Methods:
IsUserMessage(SocketMessage, out SocketUserMessage): Check if message is from userIsFromBot(SocketMessage): Check if message is from bot
DiscordUserExtensions
public static class DiscordUserExtensions
{
// Extension methods for Discord users
}
Version Constraints
The SDK supports the following version constraint formats:
==x.y.z- Exactly version x.y.z>=x.y.z- Version x.y.z or higher<=x.y.z- Version x.y.z or lower>x.y.z- Higher than version x.y.z<x.y.z- Lower than version x.y.zx.y.z- Exactly version x.y.z (same as ==)
Multiple constraints can be specified in a list:
[">=1.0.0", "<2.0.0"] // Version 1.0.0 or higher, but less than 2.0.0
Discord Namespace: QuantumKat.PluginSDK.Discord.Extensions
IMessageExtensions
public static class IMessageExtensions
{
public static bool IsUserMessage(this IMessage message, out IUserMessage? userMessage);
public static bool IsFromBot(this IMessage message);
}
Extension Methods:
IsUserMessage(IMessage, out IUserMessage?): Check if message is a user message and get typed referenceIsFromBot(IMessage): Check if message is from a bot
Error Handling
Common Exceptions
PluginLoadException
Thrown when a plugin fails to load properly.
DependencyResolutionException
Thrown when plugin dependencies cannot be resolved.
CircularDependencyException
Thrown when circular dependencies are detected between plugins.
Exception Handling Best Practices
- Catch specific exceptions where possible
- Log errors appropriately using the provided logger
- Don't let plugin errors crash the application
- Provide meaningful error messages to users
Lifecycle Events
Plugin Lifecycle
- Discovery - Plugin assemblies are scanned
- Dependency Resolution - Dependencies are analyzed and ordered
- Loading - Plugins are loaded into isolated contexts
- Instantiation - Plugin instances are created
- Initialization -
Initialize()method is called - Service Registration -
RegisterServices()method is called - Starting -
StartAsync()method is called (for threaded plugins) - Runtime - Plugin operates normally
- Stopping -
StopAsync()method is called (for threaded plugins) - Disposal - Resources are cleaned up
Service Provider Lifecycle
- Initial Build - Service provider created from main application services
- Plugin Registration - Plugins register their services
- Rebuild - Service provider rebuilt with all services
- Runtime - Shared service provider used throughout application
- Disposal - Service provider disposed during shutdown
Thread Safety
Thread-Safe Components
PluginEventRegistry- Thread-safe for concurrent message dispatchSharedServiceProvider- Thread-safe for service provider accessPluginManager- Thread-safe for plugin management operations
Non-Thread-Safe Components
- Service registration should be done during initialization only
- Plugin loading should be done on a single thread
- Settings modification should be synchronized
Performance Considerations
Memory Management
- Plugin assemblies are loaded in collectible contexts
- Service providers are properly disposed
- Event handlers maintain weak references where appropriate
Optimization Tips
- Use lazy loading for expensive services
- Implement caching for frequently accessed data
- Use object pooling for frequently allocated objects
- Minimize allocations in hot paths
Debugging and Diagnostics
Logging Categories
QuantumKat.PluginSDK.Core.PluginManager- Plugin management operationsQuantumKat.PluginSDK.Core.PluginEventRegistry- Event dispatchingQuantumKat.PluginSDK.Settings.SettingsManager- Settings operations
Diagnostic Information
- Plugin load times and success/failure status
- Dependency resolution results
- Service registration statistics
- Event handler registration and execution times