autofac

Replace registration in Autofac


I have an application which does data processing. There is

class Pipeline {
  IEnumerable<IFilter> Filters {get; set;}

I register filters implementations as

builder.RegisterType<DiversityFilter>().As<IFilter>();
builder.RegisterType<OverflowFilter>().As<IFilter>();
...

So far so good. Now, for experimentation and fine-tuning I want to be able to override any filter implementation in config file with a program(script) which would read data from stdin, process it and send data to stdout. I've implemented a module with "fileName", "args" and "insteadOf" custom properties, described module in xml and got it called.

In the module I register my "ExecutableFilter" but how do I make it run "instead of" desired service? If I try do it like this:

builder.RegisterType<ExecutableFilter>().As<DiversityFilter>()

then I get an exception " The type 'ExecutableFilter' is not assignable to service 'DiversityFilter'.". Ok, this is logical. But what are my options then?


Solution

  • Once you've overridden the registration for IFilter "After" with your wire-tap, you won't be able to resolve it from the container, as the new registration will be activated instead, hence the circular lookup.

    Instead, create and register a module that hooks into the filter's creation, and replaces the instance with the 'wire tapped' one:

    class WiretapModule : Module
    {
      override void AttachToComponentRegistration(
               IComponentRegistration registration,
               IComponentRegistry registry)
      {
        if (registration.Services.OfType<KeyedService>().Any(
              s => s.ServiceKey == After && s.ServiceType == typeof(IFilter))) 
        {
          registration.Activating += (_, e) =>
          {
            e.Instance = new WireTap(
                (IFilter)e.Instance,
                new ExecuteProvider(fileName, args));
          };
        }
      }
    }
    

    (Cross-posted to the Autofac group: https://groups.google.com/forum/#!topic/autofac/yLbTeuCObrU)