asdfDEV.Puzzle.Blazor 0.1.0-beta.11

This is a prerelease version of asdfDEV.Puzzle.Blazor.
dotnet add package asdfDEV.Puzzle.Blazor --version 0.1.0-beta.11
                    
NuGet\Install-Package asdfDEV.Puzzle.Blazor -Version 0.1.0-beta.11
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="asdfDEV.Puzzle.Blazor" Version="0.1.0-beta.11" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="asdfDEV.Puzzle.Blazor" Version="0.1.0-beta.11" />
                    
Directory.Packages.props
<PackageReference Include="asdfDEV.Puzzle.Blazor" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add asdfDEV.Puzzle.Blazor --version 0.1.0-beta.11
                    
#r "nuget: asdfDEV.Puzzle.Blazor, 0.1.0-beta.11"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package asdfDEV.Puzzle.Blazor@0.1.0-beta.11
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=asdfDEV.Puzzle.Blazor&version=0.1.0-beta.11&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=asdfDEV.Puzzle.Blazor&version=0.1.0-beta.11&prerelease
                    
Install as a Cake Tool

Puzzle

GitHub Actions Workflow Status NuGet Version GitHub Issues or Pull Requests GitHub repo size

Puzzle is a simple plugin system for .NET. It does not aim to be a fancy, best-to-ever-do-it package. It is for projects where simple, basic plugin support is needed.

Plugins are loaded in isolation; that is, they are loaded in their own AssemblyLoadContext and are isolated from the rest of the application services. Plugin services are injected alongside your application services so that you can resolve them from your DI container without any extra work. However, a plugin service will not be able to resolve your application services.

Puzzle

Download from NuGet.

This is the main package which should be used by plugin hosts. If you are writing a plugin, you will want the Puzzle.Abstractions package.

Installation

Adding plugin support to your application is as easy as one line:

...
builder.Services.AddPlugins(builder.Configuration);
...

Alternatively, for Puzzle to automatically pass itself the configuration:

...
builder.AddPlugins();
...

AddPlugins() should be called as the last step before calling builder.Build().

Configuration

Puzzle configuration options should be nested under a Plugins section.

{
  "Plugins": {
    "Locations": [
      "/path/to/plugins"
    ]
  },
  "StartupThreshold": "00:00:01.0000"
}

Locations (optional)

The locations in which Puzzle will look for plugins. Each plugin must be nested one level deep inside its own folder. For example:

.
├── ...
├── plugins                    # The directory which you will include in `Locations`
│   ├── com.company.pluginA    # The sub-directory for a plugin
|   |   |── PluginA.dll
|   |   └── ...                # Other plugin files
│   ├── com.company.pluginB    # The sub-directory for another plugin
|   |   |── PluginB.dll
|   |   └── ...                # Other plugin files
└── ...

StartupThreshold (optional)

A target time which plugin initialization should not exceed during application startup. If plugin initialization exceeds this time, a warning will be logged.

Puzzle.Abstractions

Download from NuGet.

If you are creating a plugin, this is the package for you.

Service<>

For a plugin service to be registered you must mark it with the Service<> attribute. The Service<> attribute takes a Lifetime argument. This can be Scoped, Singleton, or Transient.

NOTE: This should only be used for services which are implementing an abstraction for the host app. Let's suppose that you have the following setup:

.
├── ...
├── PluginHostApp
|   └── ...
├── PluginAbstractions
│   ├── IDataSource.cs
|   └── ...
├── SqlitePlugin
│   ├── Abstractions
│   |    ├── IConnectionFactory.cs
|   |    └── ...
│   ├── SqliteConnectionFactory.cs
│   ├── SqliteDataSource.cs
|   └── ...
└── ...

PluginHostApp is going to be looking for implementations of IDataSource, which your plugin is going to provide via SqliteDataSource. Because you want SqliteDataSource to be picked up by Puzzle, you must mark it with the Service<IDataSource> attribute. Suppose that SqliteDataSource has a dependency on IConnectionFactory, which is implemented by SqliteConnectionFactory. You would not mark SqliteConnectionFactory with the Service<IConnectionFactory> attribute because PluginHostApp does not need to know about the IConnectionFactory. Instead, you should bootstrap IConnectionFactory -> SqliteConnectionFactory as detailed below.

Your service must be public for Puzzle to pick it up.

Metadata

Your plugin must export an implementation of IPluginMetadata. If you do not export an implementation, your plugin will not be loaded.

public sealed class MyPluginMetadata : IPluginMetadata
{
  public string Id => "com.company.plugin";
  public string Name => "My Plugin";
}

Bootstrapping (optional)

If your plugin requires services to operate you can inject them via an exported IPluginBootstrapper implementation. Only one implementation is supported per plugin.

Puzzle will automatically add logging and IHttpContextAccessor for you; you should not bootstrap them yourself.

public sealed class MyPluginBootstrapper : IPluginBootstrapper
{
  public IServiceCollection Bootstrap(IServiceCollection services, IConfiguration configuration)
  {
    services.AddTransient<MyConnectionBuilder>(configuration.GetRequiredSection("Connections"));
    return services;
  }
}

The IConfiguration object which is passed in has two sources:

  1. Environment variables
  2. (Optional) A settings.json file located at the root of your plugin.

Puzzle.Blazor

Download from NuGet.

If you want to support Blazor components in your application host you will need to install Puzzle.Blazor.

...
builder.AddPlugins(config => config.AddBlazor());
...
app.MapRazorComponents<App>()
  .AddPluginComponents(app)
  ...;
...

Puzzle will automatically register all exported IComponent instances from plugins. When components from these plugins are used, Puzzle will activate the components using the plugin's DI container instead of the host application's DI container.

In order for DI to work the component must use constructor injection; NOT property injection via @inject. The notable exceptions to this rule are NavigationManager and IJsRuntime.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-beta.11 178 3/3/2025
0.1.0-beta.10 86 2/24/2025
0.1.0-beta.9 70 2/15/2025
0.1.0-beta.8 72 2/14/2025
0.1.0-beta.7 59 2/14/2025
0.1.0-beta.6 73 2/14/2025
0.1.0-beta.3.6 110 2/14/2025
0.1.0-beta.3.1 75 2/14/2025
0.1.0-beta.3 68 2/14/2025