Autofac.Extras.DynamicProxy: PropertiesAutowired not working when EnableInterfaceInterceptors and AllowCircularDependencies
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
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 18 (17 by maintainers)
Commits related to this issue
- v6 update fixed #40, unskipping test — committed to alistairjevans/Autofac.Extras.DynamicProxy by alistairjevans 4 years ago
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:
A stage in the event pipeline simply doesn’t call ‘next’ if it doesn’t want the default behaviour (or other handlers) to execute.
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 bevoid
for a few reasons:void
, does that mean theInterceptedBy
call would have to be beforeEnableInterfaceInterceptors
? If so, that… reads really oddly, like Yoda writing the fluent grammar.void
” then we’re going to have a lot ofvoid
methods.Things that randomly come across my head which are probably not good ideas but might spur some inspiration or additional other ideas…
Perhaps @alexmg , @alistairjevans , or @alsami have additional ideas?
Or maybe I’m too focused on it being an ordering issue?
Hi @tillig after investigating about this issue, I see that the reason is about when using
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
it will add anActivatedEvent
to inject properties to instance however the instance has been changed when handlingActivatingEvent
raised byEnableInterfaceInterceptors
so its property is null.My approach is to change
EnableInterfaceInterceptors
to raiseActivatedEvent
and make itsInstance
property to be settable(Currently it is read-only field https://github.com/autofac/Autofac/blob/develop/src/Autofac/Core/ActivatedEventArgs.cs#L74).I aslo has one more concern regarding the issue autofac/Autofac#860. Currently I see the order of fluent API is very important. For example:
if we swap the order of //1 //2 //3 with each others it can result to different output because it affects the order of raising event. Somehow I see it doesn’t make sense so my additional suggestion is to make the method
EnableInterfaceInterceptors
returnvoid
instead of a fluent API so that we can ensure the interception will run as a last event.What do you think about it ?