Plugin System
Package : RVR.Framework.Plugins
Description
Systeme de plugins base sur NuGet pour RIVORA Framework. Permet la decouverte, l'installation, la verification et le chargement automatique de plugins, avec validation de compatibilite et verification de signature.
Enregistrement
builder.Services.AddRvrPluginSystem(builder.Configuration);Configuration
{
"Plugins": {
"Enabled": true,
"AutoDiscovery": true,
"PluginDirectory": "./plugins",
"NuGet": {
"Sources": [
"https://api.nuget.org/v3/index.json"
],
"PackagePrefix": "RVR.Plugin.",
"AllowPrerelease": false
},
"Signature": {
"VerifySignatures": true,
"AllowUnsigned": false,
"TrustedSigners": ["Rivora", "KhalilBenazzouz"]
},
"Compatibility": {
"StrictVersionCheck": true,
"MinimumRivoraVersion": "3.0.0"
}
}
}Interface IRvrPlugin
/// <summary>
/// Interface principale pour les plugins RIVORA.
/// Etend IPlugin avec des metadonnees specifiques au framework.
/// </summary>
public interface IRvrPlugin : IPlugin
{
/// <summary>Version minimale de RIVORA requise.</summary>
string MinimumRivoraVersion { get; }
/// <summary>Liste des dependances (autres plugins requis).</summary>
IReadOnlyList<string> Dependencies { get; }
/// <summary>Metadonnees du plugin.</summary>
PluginMetadata Metadata { get; }
}
public interface IPlugin
{
string Name { get; }
string Version { get; }
string Description { get; }
Task InitializeAsync(IServiceProvider services, CancellationToken ct = default);
Task ShutdownAsync(CancellationToken ct = default);
}
public record PluginMetadata(
string Author,
string? ProjectUrl = null,
string? LicenseUrl = null,
IReadOnlyList<string>? Tags = null);Composants principaux
NuGetPluginDiscovery
Recherche les packages NuGet correspondant au prefixe RVR.Plugin.* :
public class NuGetPluginDiscovery
{
/// <summary>Rechercher des plugins disponibles sur NuGet.</summary>
Task<IReadOnlyList<PluginInfo>> SearchAsync(
string? query = null, CancellationToken ct = default);
/// <summary>Obtenir les details d'un plugin specifique.</summary>
Task<PluginInfo?> GetInfoAsync(
string packageId, CancellationToken ct = default);
}
public record PluginInfo(
string PackageId,
string LatestVersion,
string Description,
string Author,
long DownloadCount,
bool IsSigned);PluginInstaller
Installe et desinstalle les plugins depuis NuGet :
public class PluginInstaller
{
/// <summary>Installer un plugin depuis NuGet.</summary>
Task<InstallResult> InstallAsync(
string packageId, string? version = null, CancellationToken ct = default);
/// <summary>Desinstaller un plugin.</summary>
Task<bool> UninstallAsync(
string packageId, CancellationToken ct = default);
/// <summary>Lister les plugins installes.</summary>
Task<IReadOnlyList<InstalledPlugin>> ListInstalledAsync(
CancellationToken ct = default);
/// <summary>Mettre a jour un plugin vers la derniere version.</summary>
Task<InstallResult> UpdateAsync(
string packageId, CancellationToken ct = default);
}PluginSignatureVerifier
Verifie la signature NuGet des packages :
public class PluginSignatureVerifier
{
/// <summary>Verifier la signature d'un package plugin.</summary>
Task<SignatureResult> VerifyAsync(
string packagePath, CancellationToken ct = default);
}
public record SignatureResult(
bool IsValid,
bool IsSigned,
string? SignerName,
string? Reason);PluginCompatibilityChecker
Valide la compatibilite avec la version courante de RIVORA :
public class PluginCompatibilityChecker
{
/// <summary>Verifier qu'un plugin est compatible avec la version actuelle.</summary>
CompatibilityResult Check(IRvrPlugin plugin);
}
public record CompatibilityResult(
bool IsCompatible,
string? RequiredVersion,
string? CurrentVersion,
IReadOnlyList<string>? MissingDependencies);Utilisation
Decouvrir et installer des plugins
public class PluginManagerService
{
private readonly NuGetPluginDiscovery _discovery;
private readonly PluginInstaller _installer;
private readonly PluginSignatureVerifier _verifier;
public async Task<IReadOnlyList<PluginInfo>> RechercherPluginsAsync(CancellationToken ct)
{
return await _discovery.SearchAsync(query: null, ct);
}
public async Task InstallerPluginAsync(string packageId, CancellationToken ct)
{
// 1. Recuperer les informations
var info = await _discovery.GetInfoAsync(packageId, ct);
if (info is null)
throw new InvalidOperationException($"Plugin {packageId} introuvable.");
// 2. Installer depuis NuGet
var result = await _installer.InstallAsync(packageId, ct: ct);
if (!result.Success)
throw new InvalidOperationException($"Echec d'installation : {result.Error}");
// 3. Verifier la signature
var signature = await _verifier.VerifyAsync(result.PackagePath, ct);
if (!signature.IsValid)
{
await _installer.UninstallAsync(packageId, ct);
throw new SecurityException($"Signature invalide pour {packageId}");
}
}
}Lister les plugins installes
public async Task<IActionResult> GetInstalledPlugins(CancellationToken ct)
{
var plugins = await _installer.ListInstalledAsync(ct);
return Ok(plugins.Select(p => new
{
p.PackageId,
p.Version,
p.Description,
p.InstalledAt
}));
}Auto-decouverte par assembly scanning
Lorsque AutoDiscovery est active, RIVORA scanne automatiquement les assemblies dans le repertoire PluginDirectory et enregistre tous les types implementant IRvrPlugin :
// Au demarrage, les plugins sont decouverts et initialises automatiquement
builder.Services.AddRvrPluginSystem(builder.Configuration);
// Equivalent manuel :
builder.Services.AddRvrPluginSystem(options =>
{
options.AutoDiscovery = true;
options.PluginDirectory = "./plugins";
options.OnPluginLoaded = (plugin, sp) =>
{
Console.WriteLine($"Plugin charge : {plugin.Name} v{plugin.Version}");
};
});Creer un plugin
Creez un projet de classe library ciblant .NET 9 :
public class MonPlugin : IRvrPlugin
{
public string Name => "MonPlugin";
public string Version => "1.0.0";
public string Description => "Un plugin personnalise pour RIVORA";
public string MinimumRivoraVersion => "3.0.0";
public IReadOnlyList<string> Dependencies => Array.Empty<string>();
public PluginMetadata Metadata => new(
Author: "Mon Equipe",
ProjectUrl: "https://github.com/mon-equipe/mon-plugin",
Tags: new[] { "custom", "example" });
public async Task InitializeAsync(IServiceProvider services, CancellationToken ct)
{
var logger = services.GetRequiredService<ILogger<MonPlugin>>();
logger.LogInformation("MonPlugin initialise avec succes");
// Enregistrer vos services, middleware, etc.
}
public Task ShutdownAsync(CancellationToken ct)
{
// Nettoyage des ressources
return Task.CompletedTask;
}
}Publiez le package avec le prefixe RVR.Plugin. sur NuGet pour qu'il soit decouvert automatiquement.
Voir l'exemple complet dans samples/custom-plugin.
Fonctionnalites cles
- Decouverte NuGet : Recherche automatique des packages
RVR.Plugin.* - Installation / Desinstallation : Gestion complete du cycle de vie des plugins
- Verification de signature : Validation des signatures NuGet pour la securite
- Compatibilite : Verification de la version minimale de RIVORA et des dependances
- Auto-decouverte : Chargement automatique via assembly scanning au demarrage
- Metadonnees enrichies : Auteur, URL, licence, tags pour chaque plugin
- Extensible : Interface
IRvrPluginsimple a implementer