Question

I have two scenarios here that I want to solve with Ninject.Extensions.Conventions.

The first is a simple one: Whenever an instance from a namespace containing the word "service" is requested, return a singleton instance of the only matching class. I tried like so:

Kernel.Bind(service => service.FromThisAssembly()
                              .Select(theClass => theClass.Namespace.Contains("Service"))
                              .BindDefaultInterface()
                              .Configure(binding => binding.InSingletonScope()));

Some of those services get resolved, but I run into an ActivationException when the resolution chain reaches a point where Impl1 has a dependency of IService2.

What could be wrong with this binding?


The second one is probably equally simple. All classes that inherit BaseClass should be instantiated via a method. This is the resolution code I used up to now, to do that per class:

Bind<MyViewModel>().ToMethod(ctx => fac.CreateProxy<MyViewModel>())
                   .InSingletonScope();

[ Note: In this case, fac is a custom factory that builds Castle proxies.]

How can I do such a thing for a classes inheriting from, say, ViewModelBase with Extensions.Conventions?

I figured out the select part already, here it is.

Kernel.Bind(ViewModel => ViewModel.FromThisAssembly()
                                  .Select(t => t.BaseType == typeof(ViewModelBase))
                                  );

Now I need to get that factory into action...


General Questions:

  1. The binding approach of Extensions.Conventions seems to be the exact reverse of the regular way:

    • Ninject : Bind <Interface>() . To <Implementation> ()

    • Conventions : SelectAllClasses().BindDefaultInterface()

      Why is that so, or a I misunderstanding this?

  2. I used to put my bindings in a class derived from NinjectModule, and I'd preferrably continue to do so. Any reasons for not doing so when working with Extensions.Conventions?

Was it helpful?

Solution

first: Please post the exact ActivationException message + Stacktrace. Most likely the binding for IService2 is missing or there is a circular dependency.

second: Use a binding generator:

    public override void Load()
    {
        this.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses()
            .InheritedFrom<BaseClass>()
            .BindWith<ToSelfProxyBindingGenerator>()
            .Configure(binding => binding.InSingletonScope()));
    }

    public class ToSelfProxyBindingGenerator : IBindingGenerator
    {
        public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
        {
            yield return bindingRoot
                .Bind(type)
                .ToMethod(ctx => fac.CreateProxy(type));
        }
    }

Also note that the singleton scope can be defined by the IBindingGenerator or @ convention using the .Configure(..) method.

General Questions:

  1. You are correct, but i can't tell you the exact reasoning behind it.
  2. No it is perfectly fine to put conventions into different modules. We are doing this too and it works out perfectly.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top