Table of Contents

NotableDatePluginLoader Class

Definition

Namespace
Bodu.Globalization.Calendar.Plugins
Assembly
Bodu.Globalization.Calendar.Plugins.dll
Package
Bodu.Globalization.Calendar.Plugins 1.0.0
Source
NotableDatePluginLoader.cs

Loads notable-date plugins from assemblies, gating activation behind an IPluginTrustPolicy and registering the contributed algorithms with a NotableDateAlgorithmRegistry.

public static class NotableDatePluginLoader
Inheritance
NotableDatePluginLoader
Inherited Members

Examples

// Gate activation behind a strong-name trust policy, then register the plugin's algorithms.
IPluginTrustPolicy trust = new StrongNamePluginTrustPolicy(new[] { "c0ffee1234567890" });
INotableDatePlugin plugin = NotableDatePluginLoader.LoadFrom("Contoso.Calendar.Plugin.dll", trust);

NotableDateAlgorithmRegistry registry = new();
int registered = NotableDatePluginLoader.RegisterAlgorithms(plugin, registry);

// Wire the registry into the load and resolve pipeline so rules can reference the plugin keys.
NotableDateResource resource = NotableDateResourceLoader.Load(documentXml, _ => null, registry);
NotableDateService service = new(resource, new NotableDateServiceOptions { Algorithms = registry });

Remarks

Trust is evaluated before the plugin's entry-point type is activated, so an untrusted assembly's constructor never runs. The file-path overload loads the assembly into a dedicated AssemblyLoadContext.

When to use. Load a plugin with one of the LoadFrom overloads, register its contributed algorithms into a NotableDateAlgorithmRegistry with one of the RegisterAlgorithms overloads, then pass that registry to both NotableDateResourceLoader (so documents may reference the plugin's algorithm keys during validation) and the NotableDateService (so they resolve at query time). Always supply a production-grade IPluginTrustPolicy - AllowAllPluginTrustPolicy is for development only.

Logging. Each LoadFrom / RegisterAlgorithms overload accepts an optional ILogger (defaulting to Instance, so logging is opt-in). When supplied it records a trust-policy rejection (Warning), a passed trust check (Debug), an activated plugin (Information), and the number of algorithms a plugin contributed (Information). These levels are fixed.

Methods

LoadFrom(Assembly, IPluginTrustPolicy, ILogger?)

Loads the plugin declared by an already-loaded assembly after a trust check.

[RequiresUnreferencedCode("Plugin loading inspects assemblies via reflection; plugin types and their algorithm implementations cannot be statically discovered by the trimmer.")]
[RequiresDynamicCode("Plugin loading executes assemblies discovered at run time, which native AOT cannot compile ahead of time. The AOT-compatible alternative is shipping rules as data (see the calendar rule-pack roadmap).")]
public static INotableDatePlugin LoadFrom(Assembly assembly, IPluginTrustPolicy trustPolicy, ILogger? logger = null)

Parameters

assembly Assembly

The assembly declaring the plugin via NotableDatePluginAttribute.

trustPolicy IPluginTrustPolicy

The policy that must trust the assembly before its plugin is activated.

logger ILogger

The logger that receives diagnostics for the load. null selects Instance.

Returns

INotableDatePlugin

The activated plugin.

Remarks

This overload offers a weaker guarantee than the path-based LoadFrom(string, IPluginTrustPolicy, ILogger?) and must not be used for untrusted input. The assembly is already loaded when the trust policy runs, so any module initializer or type-load side effect it carries has had the opportunity to execute before the trust check - a rejection here cannot prevent code that ran at load time.

The FileHash supplied to the policy is computed by re-reading Location from disk, not from the bytes that were actually loaded, so it does not close the time-of-check/time-of-use gap that the path-based overload avoids by hashing the in-memory image it maps. For untrusted assemblies, load through the path-based overload instead.

Exceptions

ArgumentNullException

assembly or trustPolicy is null.

PluginNotTrustedException

The trust policy rejected the assembly.

PluginMissingAttributeException

The assembly does not declare a plugin attribute.

PluginActivationException

The plugin type could not be activated or is not a plugin.

LoadFrom(string, IPluginTrustPolicy, ILogger?)

Loads the plugin declared by an assembly at a file path, into a dedicated load context, after a trust check.

[RequiresUnreferencedCode("Plugin loading inspects assemblies via reflection; plugin types and their algorithm implementations cannot be statically discovered by the trimmer.")]
[RequiresDynamicCode("Plugin loading executes assemblies discovered at run time, which native AOT cannot compile ahead of time. The AOT-compatible alternative is shipping rules as data (see the calendar rule-pack roadmap).")]
public static INotableDatePlugin LoadFrom(string assemblyPath, IPluginTrustPolicy trustPolicy, ILogger? logger = null)

Parameters

assemblyPath string

The file path of the plugin assembly.

trustPolicy IPluginTrustPolicy

The policy that must trust the assembly before its plugin is activated.

logger ILogger

The logger that receives diagnostics for the load. null selects Instance.

Returns

INotableDatePlugin

The activated plugin.

Exceptions

ArgumentNullException

assemblyPath or trustPolicy is null.

ArgumentException

assemblyPath is empty.

FileNotFoundException

No file exists at assemblyPath.

DirectoryNotFoundException

A directory component of assemblyPath does not exist.

UnauthorizedAccessException

The file cannot be read.

NotableDatePluginException

The file is not a valid managed assembly image.

PluginNotTrustedException

The trust policy rejected the assembly.

PluginMissingAttributeException

The assembly does not declare a plugin attribute.

PluginActivationException

The plugin type could not be loaded or activated, or is not a plugin.

LoadFromFile(string, IPluginTrustPolicy, ILogger?)

Loads the plugin declared by an assembly at a file path, into a dedicated load context, after a trust check, returning a handle that owns the context so the plugin can later be unloaded.

[RequiresUnreferencedCode("Plugin loading inspects assemblies via reflection; plugin types and their algorithm implementations cannot be statically discovered by the trimmer.")]
[RequiresDynamicCode("Plugin loading executes assemblies discovered at run time, which native AOT cannot compile ahead of time. The AOT-compatible alternative is shipping rules as data (see the calendar rule-pack roadmap).")]
public static NotableDatePluginHandle LoadFromFile(string assemblyPath, IPluginTrustPolicy trustPolicy, ILogger? logger = null)

Parameters

assemblyPath string

The file path of the plugin assembly.

trustPolicy IPluginTrustPolicy

The policy that must trust the assembly before its plugin is activated.

logger ILogger

The logger that receives diagnostics for the load. null selects Instance.

Returns

NotableDatePluginHandle

A disposable handle owning the activated plugin and its load context.

Remarks

This overload behaves like LoadFrom(string, IPluginTrustPolicy, ILogger?) but additionally hands ownership of the plugin's collectible AssemblyLoadContext to the caller: disposing the returned handle initiates the unload. Unloading completes only once nothing references the plugin's types - a registry still holding the plugin's algorithms (or a service over that registry) keeps the context alive.

Exceptions

ArgumentNullException

assemblyPath or trustPolicy is null.

ArgumentException

assemblyPath is empty.

FileNotFoundException

No file exists at assemblyPath.

DirectoryNotFoundException

A directory component of assemblyPath does not exist.

UnauthorizedAccessException

The file cannot be read.

NotableDatePluginException

The file is not a valid managed assembly image.

PluginNotTrustedException

The trust policy rejected the assembly.

PluginMissingAttributeException

The assembly does not declare a plugin attribute.

PluginActivationException

The plugin type could not be loaded or activated, or is not a plugin.

RegisterAlgorithms(INotableDatePlugin, NotableDateAlgorithmRegistry, PluginAlgorithmRegistrationOptions, ILogger?)

Registers the algorithms contributed by a plugin with a registry under the supplied collision policy.

public static int RegisterAlgorithms(INotableDatePlugin plugin, NotableDateAlgorithmRegistry registry, PluginAlgorithmRegistrationOptions options, ILogger? logger = null)

Parameters

plugin INotableDatePlugin

The plugin whose algorithms are registered.

registry NotableDateAlgorithmRegistry

The registry to populate.

options PluginAlgorithmRegistrationOptions

The options controlling how colliding keys are treated.

logger ILogger

The logger that receives diagnostics for the registration. null selects Instance.

Returns

int

The number of algorithms registered.

Remarks

Registration is atomic: the plugin's contribution is fully staged and validated before the registry is touched, so a faulting or malformed plugin never leaves the registry partially mutated. With AllowOverride enabled, each replacement of a built-in or existing key is logged at Warning.

Exceptions

ArgumentNullException

plugin, registry, or options is null.

NotableDatePluginException

The plugin's contribution is malformed or faults, or a contributed key collides with a built-in algorithm or an existing registration while AllowOverride is false. The registry is left unchanged.

RegisterAlgorithms(INotableDatePlugin, NotableDateAlgorithmRegistry, ILogger?)

Registers the algorithms contributed by a plugin with a registry, rejecting keys that collide with built-in algorithms or existing registrations.

public static int RegisterAlgorithms(INotableDatePlugin plugin, NotableDateAlgorithmRegistry registry, ILogger? logger = null)

Parameters

plugin INotableDatePlugin

The plugin whose algorithms are registered.

registry NotableDateAlgorithmRegistry

The registry to populate.

logger ILogger

The logger that receives diagnostics for the registration. null selects Instance.

Returns

int

The number of algorithms registered.

Exceptions

ArgumentNullException

plugin or registry is null.

NotableDatePluginException

The plugin's contribution is malformed or faults, or a contributed key collides with a built-in algorithm or an existing registration. The registry is left unchanged.

Applies to

ProductVersions
.NET8, 10

See Also