Composite Pattern in .NET Core with Dependency Injection

Following on from my previous post where I implemented a decorator pattern using .NET Core dependency injection I realised that I could use the same method to create a composite pattern in a developer-friendly way.

Composite Pattern

Similar to the decorator pattern, the Composite Pattern let’s you wrap existing implementations of an interface to augment the functionality.

The difference between the two is that the decorator wraps a single instance of the interface; a composite wraps many.

interface IService {
  void DoSomething(string value);
}

class Decorator : IService {
  public Decorator(IService wrappedService) {
    //...
  }
}

class Composite : IService {
  public Composite(IEnumerable<IService> wrappedServices) {
    //...
  }
}

This is useful where you have a number of implementations of your service and you don’t want dependent classes to know whether they should call one, some or all of them.

For example, if you have a report generator that wants to send results to multiple sources you might implement several instances of IReporter:

interface IReporter {
  void Send(IReport report);
}

class ConsoleReporter : IReporter {
  public void Send(IReport report) {
    //write details to console
  }
}

class TelemetryReporter : IReporter {
  public void Send(IReport report) {
    //write stats to a telemetry service
  }
}

class EmailReporter : IReporter {
  public void Send(IReport report) {
    //send a report email to stakeholders
  }
}

Your composite reporter would construct on all other implementations of IReporter and call them in order:

class CompositeReporter : IReporter {
  private IEnumerable<IReporter> _reporters;

  public CompositeReporter(IEnumerable<IReporter> reporters) {
    _reporters = reporters;
  }

  public void Send(IReport report) {
    foreach (var reporter in _reporters)
      reporter.Send(report);
  }
}

This means that anything that needs to send a report can request a single IReporter and let the CompositeReporter worry about routing the report through the correct concrete implementations.

Default DI Behaviour

As discussed in the previous post, the default behaviour of the .NET Core Dependency Injection framework is to provide the last-registered copy of an interface, or all registered copies for an IEnumerable.

services.AddScoped<IService, ConcreteService1>();
services.AddScoped<IService, ConcreteService2>();
services.AddScoped<IService, ConcreteService3>();

//later
const service = serviceProvider.GetRequiredService<IService>();
// service is instance of ConcreteService3

const allServices = serviceProvider.GetRequiredService<IEnumerable<IService>>();
// allServices contains one instance of all 3 registered implementations

What we need is a way to register a new type to replace the existing registrations and take them in as a constructor dependency.

class Composite : IService {
  public class Composite(IEnumerable<IService> services) {
    //...
  }
}

//BAD - throws StackOverflowException when resolved!
services.AddScoped<IService, Composite>();

Unfortunately the default behaviour of the DI framework is to attempt to fulfil the request for all IService implementations with…another instance of Composite! One StackOverflowException later and we’re back to the drawing board.

How can we make this play nicely with DI?

Borrowing from the Last Post

After some digging through the ASP.NET Core source code in the last post we came up with a couple of useful helpers that we can re-use here: CreateFactory and CreateInstance.

ActivatorUtilities.CreateFactory generates a factory function to create an instance of ConcreteType from the service provider with some services provided explicitly.

var objectFactory = ActivatorUtilities.CreateFactory(
  typeof(ConcreteType), 
  new[] { typeof(IService) });

CreateInstance creates an instance of a service from a ServiceDescriptor.
We can get instances of ServiceDescriptor from the service collection and use these to create previously-registered types.

public static object CreateInstance(this IServiceProvider services, ServiceDescriptor descriptor)
{
  if (descriptor.ImplementationInstance != null)
    return descriptor.ImplementationInstance;

  if (descriptor.ImplementationFactory != null)
    return descriptor.ImplementationFactory(services);

  return ActivatorUtilities.GetServiceOrCreateInstance(services, descriptor.ImplementationType);
}

With these tools we can define our desired composite behaviour.

Extract Existing Registrations

When we register a new composite we want to

  1. Remove all existing registered services for the same interface
  2. Insert the composite implementation
  3. Pass instances of all removed implementations into the constructor of the composite

Remove Existing Registrations

IServiceCollection extends IEnumerable so we can filter it down to get the services that match the interface of the composite class.

public static void AddComposite<TInterface, TConcrete>(this IServiceCollection services)
  where TInterface : class
  where TConcrete : class, TInterface
{
  //get a list of existing registrations matching the target interface
  var wrappedDescriptors = services
    .Where(s => s.ServiceType == typeof(TInterface))
    .ToList();

  //remove each from the service collection
  foreach (var descriptor in wrappedDescriptors)
    services.Remove(descriptor);

  //...
}

We call ToList to we get a persistent list of the items and then remove them from the original collection.

Add Composite Implementation

Next up we want to insert the definition of our composite class, and we’re going to use the ActivatorUtilites helper mentioned above.

var objectFactory = ActivatorUtilities.CreateFactory(
  typeof(TConcrete),
  new[] {
    typeof(IEnumerable<TInterface>)
  });

Here we create a factory function that can be used with a service provider to resolve an instance of TConcrete (i.e. our composite class) with any parameters of type IEnumerable{TInterface} manually specified by us.

The objectFactory forms the basis of a new ServiceDescriptor to add to the collection.

var compositeDescriptor = ServiceDescriptor.Describe(
  typeof(TInterface),
  serviceProvider => (TInterface)objectFactory(serviceProvider, new [] {
    /* todo: inject original services here */
  },
  ServiceLifetime.Scoped);
);

services.Add(compositeDescriptor);

Note: in this example I have hard-coded a lifetime of Scoped for the service. We can improve on this below but it will do for now.

Inject Original Services

We still need to inject instances of the original services that we removed. We recorded their service descriptors in wrappedDescriptors and we can now combine those with the CreateInstance extension method above to populate our constructor parameter.

var compositeDescriptor = ServiceDescriptor.Describe(
  typeof(TInterface),
  serviceProvider => (TInterface)objectFactory(serviceProvider, new [] {
    wrappedDescriptors
      .Select(d => serviceProvider.CreateInstance(d))
      .Cast<TInterface>()
  },
  ServiceLifetime.Scoped);
);

Now all of the wrapped services will be created through the service provider and passed to our composite.

This approach may seem long winded but it has the advantage that any other dependencies of either the wrapped services or our composite will also be injected from the service provider with no further input from us!

Calculate Lifetime Scope

The hard-coded lifetime scope isn’t ideal, and whilst we could push the onus onto the caller to specify a scope we can do slightly better and infer it from the existing registrations.

If the composite depends on a Scoped instance then it can be either Scoped or Transient without a problem, but cannot be Singleton as it would not have access to scoped dependencies.

We can infer the maximum scope of the composite by taking the most specific scope of it’s dependencies. The ServiceLifetime enum is defined with the least specific scope (Singleton) as 0 so we can select the maximum value to get the most specific.

Pull it All Together

Combining all of the above we get the following extension method:

public static void AddComposite<TInterface, TConcrete>(this IServiceCollection services)
  where TInterface : class
  where TConcrete : class, TInterface
{
  var wrappedDescriptors = services.Where(s => s.ServiceType == typeof(TInterface)).ToList();
  foreach (var descriptor in wrappedDescriptors)
    services.Remove(descriptor);

  var objectFactory = ActivatorUtilities.CreateFactory(
    typeof(TConcrete), 
    new[] { typeof(IEnumerable<TInterface>) });

  services.Add(ServiceDescriptor.Describe(
    typeof(TInterface),
    s => (TInterface)objectFactory(s, new[] { wrappedDescriptors.Select(d => s.CreateInstance(d)).Cast<TInterface>() }),
    wrappedDescriptors.Select(d => d.Lifetime).Max())
  );
}

Now we can wrap up as many services as we want in a composite with one line

var services = new ServiceCollection();
services.AddSingleton<IReporter, ConsoleReporter>();
services.AddScoped<IReporter, TelemetryReporter>();
services.AddTransient<IReporter, EmailReporter>();

services.AddComposite<IReporter, CompositeReporter>();
Advertisements

Find .NET Core packages in all projects

In a quick aide-memoire for next time I need to use it: here’s a Powershell snippet that will return a list of all unique package names in all .NET Core projects under the current folder:

get-childitem -recurse -filter *.csproj |
  foreach { get-content $_.FullName } |
  select-string -pattern "PackageReference Include=""(.+?)""" |
  % { $_.matches[0].Groups[1].Value } |
  sort-object -unique

Line by line…

  • Get all *.csproj in the current and child folders
  • Read the content of each one
  • Extract every line that matches the specific regex and extract the name of the package
  • Grab the package name group
  • Sort & filter to unique values

This outputs something like

CommandLineParser
CsvHelper
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console

Stop Agonising Over Tiny Details

I recently started a new side project using React and – having not used React in anger before – wanted to get off on the right foot.

And by “on the right foot” I apparently decided that I meant “with the perfect folder structure for my code”.

Obviously we can all agree that folder structure is the most important predictor of code quality  (<sarcasm/>) so I spent hours agonising over whether to separate  components from screens or whether to group all actions together in an actions folder and a hundred other basically-irrelevant details. I read blog posts. I tried template project generators. I poured over a huge number of “sample” GitHub repos (every one different, of course).

To reiterate: this was for a new, greenfield side project. I spent hours of my limited time worrying about where to put all the code instead of…writing any of that code!

facepalm

Hence this post. This post sits here as a reminder to myself to STOP AGONISING OVER UNIMPORTANT THINGS.

And you know what? I changed the entire structure after a week anyway.

Finding Freedom in “JavaScript Fatigue”

A lot of people have spoken about “JavaScript fatigue”: the idea that there are so many new frameworks, tools and ideas available to the average JavaScript developer that it’s impossible to keep up. I thought I’d add my opinion.

When I started learning JavaScript it used to be that I would try to keep up with everything. I suspect now that I just didn’t know how much was out there, but it really felt like that was an acheivable target. I would make a real effort to not only read up on new frameworks & libraries but to try them out: maybe a quick tutorial, maybe a few introductory posts, maybe even a small project.

Now, things have changed and it is obvious to most of us that there is no way you can invest that much time in every new thing that comes out.

For me, this is not a bad thing. In fact, I find it pretty liberating.

The whole situation reminds me a little bit of when I first joined Twitter. I was following maybe 20 people and I would make a real effort to read every single tweet. Ridiculous, right? But still I tried. Then I started following more people and then more people and with every extra piece of content it became less and less realistic to get through everything.

So I let go. I had to.

I couldn’t keep up with everything so I stopped trying to do the impossible and learned to let the mass of information wash over me. If something particularly catches my eye then I can read up on it but if I miss something? Who really cares?

Nowadays it feels the same with JavaScript frameworks. I may never have a chance to get my hands dirty with everything that comes out. In fact, I may never even hear of some of them. But I don’t worry any more about trying to keep up and if something really is the next big thing… well, I’m pretty sure I’ll hear about it soon enough.

Cleaning up Resources using MutationObserver

Cleaning up resources?

Let’s say you’ve written a shiny new component in your favorite framework and somewhere along the way you’ve allocated a resource that cannot be automatically cleaned up by the browser.

Maybe you attached an event handler to the resize event on the window.  Maybe you passed a callback to a global object.  Whatever the case, you need to tidy up those resources at some point.

Easy enough, right?  Put a dispose method on our object to clean up it’s leftovers and make sure it’s called before the object is discarded.

Problem solved?

Problem not quite solved

What if, for whatever reason, your component doesn’t have control over the parent?  You could trust that the user will do the right thing and call dispose for you but you can’t guarantee it.

As an alternative, can we automatically clean up our resources as soon as our containing DOM element is removed?

Yes.  Yes we can.

Using MutationObserver

The MutationObserver API (which has pretty great browser support) lets you listen to changes made to a DOM node and react to it.  We can use it here to perform our cleanup.

When we create an instance of MutationObserver we specify a callback that gets details of changes made to the parent.  If those changes include the removal of our target element then we can call dispose.

Here we are observing the parent of our target node, not the node itself (which would not be notified if removed).  We need to specify { childList: true } as the second parameter to be notified of additions and removals of child items.

Disposing the Observer

Finally, we need to make sure that the observer itself doesn’t cause a memory leak!  The observer is connected to the parentElement which (we assume) will still be hanging around, so we need to make sure that we disconnect it as part of disposal.

With everything pulled together the final version looks like this…

Supporting SignalR Client Handlers after Connection Start

(Yes, that is a pretty specific post title but then this is a pretty specific problem…)

In general, when you create a new SignalR connection you are obliged to have already defined any of your handlers on the connection.yourHubName.client object. This allows SignalR to discover those handlers and hook them up to the incoming messages.

Problem: Multiple connection sources

This approach is fine as long as you have a single place from which you are starting your connection but what if you have 2 hubs, 2 separate client handlers…2 of everything?

They will both automatically share a SignalR connection so you can end up with a bit of a race condition where the first handler to start the connection will be the only handler registered.  Imagine the following handlers…

function MyFirstHandler() {
  //assign the handler
  $.connection.myHub1.client.method1= function() { ... };

  //start the connection
  $.connection.myHub1.connection.start();
}

function MySecondHandler() {
  //assign the handler
  $.connection.myHub2.client.method2= function() { ... };

  //start the connection
  $.connection.myHub2.connection.start();
}

//...some time later...
new MyFirstHandler()
//...and even later still...
new MySecondHandler()

By the time we create MySecondHandler we have already created the connection and so method2 is not attached and will never be invoked.

Solution: Proxy implementation

We can work around this by replacing the connection.yourHubName.client object (normally just a POJO) with something that is aware of the available server methods.  The new client then exposes stubs to which SignalR can connect before our MySecondHandler can provide the “real” handler implementations.

//before creating any handlers
$.connection.myHub1.client = new SignalRClient(['method1','otherHandler']);
$.connection.myHub2.client = new SignalRClient(['method2']);

The SignalRClient implementation has 3 requirements for each named handler:

  1. Always return a valid handler function for SignalR to bind, even if the real handler hasn’t been assigned yet
  2. If the real handler has been assigned, invoke that when the handler is invoked (with all args etc.)
  3. Allow client.myHandler = function(){} assignments for compatibility with existing code

The last requirement means that we need to use Object.defineProperty with custom getter and setter implementations.  The getter should always return a stub method; the setter should store the real handler; and the stub method should invoke the real handler (if assigned).

function SignalRClient(methods) {
	this._handlers = {};
	methods.forEach(this.registerHandler.bind(this));
}

SignalRClient.prototype.invokeHandler = function(name) {
	var handler = this._handlers[name];
	if (handler) {
		var handlerArgs = Array.prototype.slice.call(arguments, 1);
		handler.apply(this, handlerArgs);
	}
}

SignalRClient.prototype.registerHandler = function(name) {
	var getter = this.invokeHandler.bind(this, name);
	Object.defineProperty(this, name, {
		enumerable: true,
		get: function() { return getter },
		set: function (value) { this._handlers[name] = value; }.bind(this)
	});
}

Note that our defined properties must also be marked as enumerable so that the SignalR code picks up on them when it attempts to enumerate the client handler methods.

Now – provided we know the available methods up front – we can start the connection whenever we like and assign our handlers later!

Custom Operation Names with Swashbuckle 5.0

This is a post about Swashbuckle –  a .NET library that seamlessly adds Swagger support to WebAPI projects.  If you aren’t familiar with Swashbuckle then stop reading right now and go look into it – it’s awesome.

library-api

Swashbuckle has recently released version 5.0 which includes (among other things) a ridiculous array of ways to customise your generated swagger spec.

One such customisation point allows you to change the operationId (and other properties) manually against each operation once the auto-generator has done it’s thing.

Why Bother?

Good question.  For me, I decided to bother for one very specific reason: swagger-js.  This library can auto-generate a nice accessor object based on any valid swagger specification with almost no effort, whilst doing lots of useful things like handling authorization and parsing responses.

swagger-js uses the operationId property for method names and the default ones coming out of Swashbuckle weren’t really clear or consistent enough.

Injecting an Operation Filter

The means for customising operations lies with the IOperationFilter interface exposed by Swashbuckle.

public interface IOperationFilter
{
  void Apply(Operation operation, 
    SchemaRegistry schemaRegistry, 
    ApiDescription apiDescription);
}

When implemented and plugged-in (see below), the Apply method will be called for each operation located by Swashbuckle and allows you to mess around with its properties.  We have a very specific task in mind so we can create a SwaggerOperationNameFilter class for our purpose:

public class SwaggerOperationNameFilter : IOperationFilter
{
  public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
  {
    operation.operationId = "???";
  }
}

When you installed the Swashbuckle nuget package it will have created a SwaggerConfig file in your App_Start folder.  In this file you will likely have a long and well-commented explanation of all available configuration points, but to keep things simple we can insert the reference to our filter at the end:

GlobalConfiguration.Configuration
  .EnableSwagger(c =>
  {
    //...
    c.OperationFilter<SwaggerOperationNameFilter>();
  });

Getting the Name

At this point you have a lot of flexibility in how you generate the name for the operation.  The parameters passed in to the Apply method give you access to a lot of contextual information but in my case I wanted to manually specify the name of each operation using a custom attribute.

The custom attribute itself contains a single OperationId property…

[AttributeUsage(AttributeTargets.Method)]
public sealed class SwaggerOperationAttribute : Attribute
{
  public SwaggerOperationAttribute(string operationId)
  {
    this.OperationId = operationId;
  }

  public string OperationId { get; private set; }
}

…and can be dropped onto any action method as required…

[SwaggerOperation("myCustomName")]
public async Task<HttpResponseMessage> MyAction()
{
  //…
}

Once the attributes are in place we can pull the name from our filter using the ActionDescriptor

operation.operationId = apiDescription.ActionDescriptor
  .GetCustomAttributes<SwaggerOperationAttribute>()
  .Select(a => a.OperationId)
  .FirstOrDefault();

Voila!