1

I am using ninject.extensions.conventions to bind all implementations in a given assembly and tag them with the assembly name as the binding's metadata. I can pull these items back out using a Get and supplying a func as standard.

What I would like to know is does this func apply to all children resolved also? My worry is that while my logic works now, if I add more bindings that satisfy any children more than once ninject will throw.

Code Sample:

_kernel.Bind(binder => binder.From(new[] { pathToAssembly })
                             .SelectAllClasses()
                             .BindAllInterfaces()
                             .Configure(binding => 
                                        binding.WithMetadata("context", 
                                                             assemblyName)));


 _kernel.Get<IRootDependency>
         (metadata => metadata.Get<IRootDependency>("context") == 
                                                   assemblyName);

// Bound from convention above.
RootDependencyBase: IRootDependency
{
  Public RootDependencyBase(IChildDependency Child) {};
}

// Bound using the convention above with the same MetaData Tag.
ChildDependencyFromSameAssembly : IChildDependency {}

// Bound using a differing convention and does not have the same MetaData tag.
ChildDependencyFromOtherAssembly : IChildDependency {}

Based on the above sample I know that IRootDependency will be resolved to the correct binding based on the metadata filter.

What I am looking to find out is is the following true.

This filter does not feed down the dependency chain. IChildDependency will throw an exception because although the binding specified MetaData it is not queried.

deanvmc
  • 5,957
  • 6
  • 38
  • 68
  • Are you worrying about two or more implementations of same interface/abstract class in the given assembly? Sure, in this case you'll get an exception because Ninject couldn't resolve dependency. – Akim Jan 14 '13 at 10:26
  • @Akim Two or more child implementations. The parent will resolve fine because of the metadata constraint func. I am looking to see if the same constraint will be applied to any child resolution also. – deanvmc Jan 14 '13 at 11:36
  • Could you provide an example? Here is [my example when `Ninject.Extensions.Conventions` would not resolve automaticaly dependencies and throw an `ActivationException: Error activating IDependency. More than one matching bindings are available.`](https://gist.github.com/4530019) – Akim Jan 14 '13 at 13:24
  • @Akim I've added code to show you what I mean. – deanvmc Jan 14 '13 at 13:58

2 Answers2

4

Constraints are applyed to the root resolution only. In case you have multiple assemblies containing a child dependency you will get an exception.

To get it work you have to add a condition to the bindings. E.g like this:

.When(r => r.ParentContext == null || r.ParentContext.Binding.Metadata.Get<string>("context", null) == assemblyName)

Or get the root request (request.ParentRequest until parentRequest is null) and apply the constraint

.When(r => GetRootRequest(r).Constraint(r))
Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • Thanks Remo. One last item for clarity. It looks like it is the second one I want. Is there a way to apply the second option in my current binding as a given service could be both the root and a child depending on the caller. Normally this isn't an issue but in my instance (Web API) there is no single root. Something like .Configure(x => x.WithMetadata("context", assemblyName) || x.When(r => GetRootRequest(r).Constraint(r)))); – deanvmc Jan 14 '13 at 14:53
2

Yes, in case if your examples will has another implementation of IChildDependency in same assembly as ChildDependencyFromSameAssembly you'll get exception ActivationException with message:

Error activating IDependency
More than one matching bindings are available.

You have to provide exact criteria to Ninject to find what implementation of IChildDependency, from same assembly, will suits better

Akim
  • 8,469
  • 2
  • 31
  • 49