Replace Autofac Registration

I have an application that does data processing. Exists

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

I register filter 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 override any filter implementation in the configuration file using a program (script) that will read data from stdin, process and send data to stdout. I implemented a module with custom properties "file_name", "args" and "instead ofOf", described the module in xml and got it.

In the module I register my “ExecutableFilter”, but how do I get it to run “instead of the“ desired service ”? If I try to do it like this:

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

then i get an exception. The type "ExecutableFilter" is not assigned to the "DiversityFilter" service. ". Well, that’s logical. But what are my options?

+6
autofac
source share
2 answers

After you redefined the registration for IFilter “After” using wires, you cannot allow it from the container, because instead a new registration will be activated, therefore, a circular search.

Instead, create and register a module that connects to the creation of the filter, and replaces the instance with "wired connected":

 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 += (s, e) => { e.Instance = new WireTap((IFilter)e.Instance, new ExecuteProvider(fileName, args)) }; } } } 

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

+9
source share

What you are describing is container handling, part of the business logic. The challenge is to maintain a separation of concerns here. IMO, the container should do what it should do, it is the collection and maintenance of instances or collections. In this case, he should not do "instead." I would rather enrich the services with enough information for the pipeline to make a decision.

Enrichment can be accomplished by creating an ExecutableFilter implementation of a clearer interface.

 interface IInsteadOfFilter : IFilter { } ... builder.RegisterType<ExecutableFilter>().As<IFilter>(); ... class Pipeline { IEnumerable<IFilter> Filters {get;set;} public void DoTheFiltering() { var filters = Filters.OfType<IInsteadOfFilter>(); if (!insteadof.Any()) filters = Filters; foreach(var filter in filters) { ... } } 

You can also solve this problem using the metadata infrastructure , which gives us an even more expressive way to differentiate services.

+1
source share

All Articles