I am basing most of my current implementation off the information provided here:
Ninject Intercept any method with certain attribute?
I use a custom planning strategy class which looks for all methods with given attributes (not ninject interceptor attributes) which will then get proxied if it matches the criteria.
An example of usage would be:
Kernel.Components.Add<IPlanningStrategy, CustomPlanningStrategy<LoggingAttribute, LoggerInterceptor>>();
This would then look for any methods which have a [Logging]
attribute and will then use the logging interceptor.
However I am currently getting InvalidProxyConstructorArgumentsException from dynamic proxy when it is trying to proxy the methods with related attributes on. Now I remember reading that you need virtual methods, however I do not remember seeing that you HAD to have a parameterless constructor.
All bindings are done against interfaces, and the AOP interceptors happen via attributes and the custom proxy planning class mentioned in the link above.
So is there a way to get dynamic proxy (or the linfu version) to proxy the classes which have constructors with dependencies? (All dependencies are in the Kernel so its not like they cannot be resolved).
An alternate approach would be to use a convention based binding for all classes with a method with a
[Logging]
attribute. However, this means that adding a[Logging]
attribute to a method will influence the binding of the object, which may be undesired.So this is how it would work (verified to work):
And a test:
Results in the following console output:
Looking at the proxy generating code: https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs
one can see that ninject's dynamic proxy extension is only passing
ConstructorArgument
s to the Castle Dynamic Proxy Generator.So - without changes to the ninject extension or creating your own - you need to pass all dependencies as constructor arguments. You could also try out whether property / method injection works (see https://github.com/ninject/ninject/wiki/Injection-Patterns).
If you control the code you could add interfaces to the proxied classes and then use an "interface proxy with target". This allows to decouple proxy instantiation from target (proxied class) instantiation --> target can have dependencies ctor injected without any changes to ninject (-extensions).
Clarification: Having the following class which should be proxied:
And the following binding:
And then retrieving a
Foo
from the ninject container:won't work.
Putting all constructor arguments on the ninject context to make it work
However, we can change the retrieving of
Foo
to make it work:Now this is suboptimal because ninject is not doing dependency resolution automatically.
Adding interface to proxied class to make it work better
We can work around the issue by using a "interface proxy with target". First, we add an interface to the proxied class:
And then we change the binding to:
And then retrieving a
Foo
from the ninject container:works.
Another, possibly easier (&uglier?) solution According to @Daniel this works: Add two constructor to the proxied type:
protected
constructor without parameters. This one is for DynamicProxy to create the proxy.public
/internal
constructor with the arguments, to be used by ninject to instantiate the proxied type.Ninject will automatically pick the constructor with the most arguments it can resolve.