質問

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?

役に立ちましたか?

解決

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.
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top