Skip to content

[Design] PluginSystemOptions.RegisteredALCs is hidden mutable state — side-channel coupling between PluginLoader and PluginManager #16

@pournasserian

Description

@pournasserian

Summary

PluginSystemOptions contains an internal mutable list of AssemblyLoadContext instances (RegisteredALCs). This list is populated by PluginLoader and consumed by PluginManager. Using a public options/configuration object as a hidden communication channel between two components is an anti-pattern: the options class should carry only configuration values, not mutable runtime state.

Location

Plugins/FluentCMS.Infrastructure.Plugins/PluginSystemOptions.cs — line 51

Problematic Code

internal List<AssemblyLoadContext> RegisteredALCs { get; } = [];

Impact

  • Hidden coupling: PluginLoader and PluginManager are implicitly coupled through the shared options object with no documented contract.
  • Unexpected mutation: Any component that holds a reference to PluginSystemOptions can observe or modify the ALC list, which should be an implementation detail.
  • Testing difficulty: Creating a PluginSystemOptions instance in tests doesn't give the expected clean state without knowing about this hidden list.
  • Violation of SRP: PluginSystemOptions now serves two roles: configuration data-bag and runtime ALC registry.

Recommendation

Remove RegisteredALCs from PluginSystemOptions and change LoadPluginTypes to return a result type that packages both outputs together:

public record PluginLoadResult(
    IReadOnlyList<Type> PluginTypes,
    IReadOnlyList<AssemblyLoadContext> LoadContexts
);

// PluginLoader.LoadPluginTypes() returns PluginLoadResult
// PluginManager receives PluginLoadResult directly

This makes the data-flow explicit and removes the hidden state from the configuration object.

Severity

🔵 Design / Maintainability

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions