question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

PropertiesAutowired not working when EnableInterfaceInterceptors and AllowCircularDependencies

See original GitHub issue

I use Autofac DynamicProxy2 do AOP logging. If I register like this:

builder.RegisterAssemblyTypes(assemblys.ToArray()).Where(t => t.Name.EndsWith("ServiceImpl"))
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope()
                .PropertiesAutowired()
                .EnableInterfaceInterceptors()
                .InterceptedBy(typeof(LogInterceptor));
            ;

then ValuesServiceImpl instance can be auto wire to property, like this:

public class ValuesController : ApiController
    {
        public IValuesService ValuesService { get; set; }
    }

But if I use PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)

builder.RegisterAssemblyTypes(assemblys.ToArray()).Where(t => t.Name.EndsWith("ServiceImpl"))
                    .AsImplementedInterfaces()
                    .InstancePerLifetimeScope()
                    .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                    .EnableInterfaceInterceptors()
                    .InterceptedBy(typeof(LogInterceptor));

then PropertiesAutowired not working, ValuesService property is null.

In my project I must allow Circular Dependencies, and I prefer use EnableInterfaceInterceptors instead of EnableClassInterceptors

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:18 (17 by maintainers)

github_iconTop GitHub Comments

1reaction
alistairjevanscommented, Mar 25, 2020

My two cents:

My experience of writing extensible systems has shown me that having a specific order value assigned to an event handler is an eventual recipe for disaster (even if it fixes the immediate problem). When two extension writers both set the same order value, you’re back to square one. Or there’s a competing race to have the highest/lowest order value. It becomes something of a nightmare.

The most effective event-handling solution I’ve found in such systems is to have a generous number of clearly defined events that are strongly ordered, with event handlers attached to each that are not ordered. Autofac already has a number of such events (Preparing, Activating, Activated, etc), but they could be extended/cleaned up.

An Alternative

An alternate approach/improvement (in my opinion) to the event handling model when using ‘declarative’ event ordering (like we appear to have in the fluent set-up, and @alsami points out is pretty far-reaching already) might be to use a middleware-style event pipeline model for event handling.

Treating each event like a request to be processed allows a given handler to consider the before/after the ‘next’ event handler, with the last stage of the pipeline being the Autofac Core behaviour. You can see an implementation of this in AutoStep, a project I’m working on right now.

In such a model, the three Autofac event ‘types’ would be Preparation, Activation and Release.

An event handler would look like:

void EventHandler(ActivationEventArgs args, Action<ActivationEventArgs> next) 
{
         // Before Activation
        next(args);
        // After Activation
}

A stage in the event pipeline simply doesn’t call ‘next’ if it doesn’t want the default behaviour (or other handlers) to execute.

1reaction
tilligcommented, Mar 24, 2020

Sounds like this overlaps a lot with autofac/Autofac#860, which is also about EnableInterfaceInterceptors() and event ordering.

I’ve noodled on this for the last day or so since you made some proposals. In an ideal world I think the fluent builder syntax should just “do the right thing.” This skips over a lot of important details to be sure, but the idea is that the order technically shouldn’t matter.

I’m afraid of changing EnableInterfaceInterceptors to be void for a few reasons:

  • It’d be breaking big time, and while I get that some things do need to be breaking changes, it’d be really nice to avoid it.
  • It will change the fluent semantics. If it returns void, does that mean the InterceptedBy call would have to be before EnableInterfaceInterceptors? If so, that… reads really oddly, like Yoda writing the fluent grammar.
  • It seems like we could very easily run into one of these ordering issues again, and if the answer is “change the thing that needs to be last to void” then we’re going to have a lot of void methods.

Things that randomly come across my head which are probably not good ideas but might spur some inspiration or additional other ideas…

  • What if we had more events in the pipeline? A richer event chain, like pre-activating, activating, post-activating, pre-activated, activated, post-activated… or whatever. Maybe better names. Could we control things in the lifecycle ordering better with more events?
  • What if we could declare event handler order? Like action filters in ASP.NET MVC where you can set an order value and before they get run they get sorted by order. I don’t think that’s something that comes “out of the box” with events but maybe we could do something internally that makes it seem like it’s ordered?

Perhaps @alexmg , @alistairjevans , or @alsami have additional ideas?

Or maybe I’m too focused on it being an ordering issue?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Autofac DynamicProxy2 PropertiesAutowired not working ...
I use Autofac DynamicProxy2 do AOP logging. If I register like this: builder.RegisterAssemblyTypes(assemblys.ToArray()).Where(t => t.Name.
Read more >
Dependency injection — Autofac
So we need to call the .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies) method to allow dependencies and we need to ...
Read more >
Circular Dependencies — Autofac 7.0.0 documentation
The properties must be writeable. Register the types using PropertiesAutowired . Be sure to set the behavior to allow circular dependencies.
Read more >
Autofac Documentation
This TodayWriter is where it all comes together. // Notice it takes a constructor parameter of type. // IOutput - that lets the...
Read more >
C# (CSharp) Autofac ContainerBuilder.RegisterGeneric ...
Autofac is an IoC container for .NET applications. It allows you to resolve your dependencies automatically. The Autofac ContainerBuilder RegisterGeneric ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found