RonSijm.BlazorAspect 1.0.2

The ID prefix of this package has been reserved for one of the owners of this package by NuGet.org. Prefix Reserved
dotnet add package RonSijm.BlazorAspect --version 1.0.2
NuGet\Install-Package RonSijm.BlazorAspect -Version 1.0.2
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="RonSijm.BlazorAspect" Version="1.0.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add RonSijm.BlazorAspect --version 1.0.2
#r "nuget: RonSijm.BlazorAspect, 1.0.2"
#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.
// Install RonSijm.BlazorAspect as a Cake Addin
#addin nuget:?package=RonSijm.BlazorAspect&version=1.0.2

// Install RonSijm.BlazorAspect as a Cake Tool
#tool nuget:?package=RonSijm.BlazorAspect&version=1.0.2

RonSijm.BlazorAspect

.NET NuGet codecov

A C# Blazor library To assign Aspects / Behaviors to a page or component through assigning an interface, attribute, or type any type expression

NuGet: https://www.nuget.org/packages/RonSijm.BlazorAspect/

What is this library:

This library aims to add Aspect to Blazor pages or components, and allows you to basically delegate OnAfterRender to a standalone class.

Practically this library introduces a hook after OnParametersSetAsync and Before OnAfterRender that can be used by interface based subscribers.

In usual C# you might want to implement similar behavior through PostSharp or Fody, and handle the AOP side through code-weaving during compile time, but in Blazor those approaches are not always ideal, and it's sometimes preferred to handle things run-time

Or in usual C# you would lean towards Castle DynamicProxy and interceptors - that's not doing to work very well in Blazor

Youtube Video Demo:

Video of RonSijm.BlazorAspect

Example Use-Cases

A good example of a use-case is Fluxor.Blazor.

Fluxor.Blazor allows you to "Automagically" subscribes to IState components through inheriting from a FluxorComponent
The downside of that, is that you have to inherit all your classes from the FluxorComponent. And as you (should) know - "favor composition over inheritance"

This library will allow you to replace the inheritance with composition though interfaces, attributes or type conditions.

Getting started:

To enable BlazorAspects:

In your program.cs simply start adding aspects with a the line such as:
builder.Services.WhenAssignableFrom(typeof(ILogRendering)) .UseAspect(component => LogRenderingAction.Log(component));

For example:

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);

        builder.Services.WhenAssignableFrom(typeof(ILogRendering))
                        .UseAspect(component => LogRenderingAction.Log(component));
		// Other stuff
	}
}

WhenAssignableFrom is expected to be the most common use-case, you can also use WhenHasAttribute to use attributes instead of interfaces.

Then you simply add the line:
builder.Services.WhenHasAttribute(typeof(LoggingAttribute)) .UseAspect(component => LogRenderingAction.Log(component));

you can also use your own type condition :

For example:

builder.Services.WhenType(x => x.IsAssignableFrom(typeof(ILogRendering))) .UseAspect(component => LogRenderingAction.Log(component));

or even:

builder.Services.WhenType(x => x != null)) .UseAspect(component => LogRenderingAction.Log(component));

To enable logging:

To enable logging, you can add the following line to your program.cs:

It used the default ILogger, and can be configured as such.

    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
		
        // I think you have to add this before building
        builder.Logging.AddFilter("RonSijm.BlazorAspect.AspectActivation", LogLevel.Trace);
		
        var application = builder.Build();

        //Add this after building
        application.Services.EnableComponentResolveLogging();

        await application.RunAsync();
    }
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.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
1.0.2 182 4/11/2023
1.0.1 155 4/7/2023
1.0.0.1 162 4/6/2023
1.0.0 156 4/5/2023
0.1.0-alpha 119 4/5/2023