Ninject and redirected types (as is known in Castle Windsor)

Castle Windsor has a feature called redirected types, where you can have one component configuration for multiple services. For instance:

var container = new WindsorContainer();
container.Register(
   Component.For<Bar>().Forward<IFoo>()
      .ImplementedBy<FooBar>());
var foo = container.Resolve<IFoo>();
var bar = container.Resolve<Bar>();
Debug.Assert(foo == bar);

(this Debug.Assert job works because Windsor by default registers things as single)

How to achieve this in Ninject (version 2)?

+3
source share
2 answers

I am interested to know if anyone else can come up with a better solution, but there is an option here:

Use a special IProvider when linking to a transition:

public class ForwardProvider<ForwardType> : Ninject.Activation.IProvider
{
    #region IProvider Members
    public object Create( IContext context )
    {
        return context.Kernel.Get<ForwardType>();
    }

    public Type Type
    {
        get { return typeof( ForwardType ); }
    }
    #endregion
}

and then when binding:

IKernel kernel = new StandardKernel();
kernel.Bind<ITestAdapter>().To<TestAdapter>().InSingletonScope();
kernel.Bind<IAnotherAdapter>().ToProvider<ForwardProvider<ITestAdapter>>();

and my test:

var foo = kernel.Get<ITestAdapter>();
foo.Indicator = 5;

var bar = kernel.Get<TestAdapter>();
Assert.That( foo.Indicator, Is.EqualTo( 5 ) );

var baz = kernel.Get<IAnotherAdapter>();
Assert.That( baz.Indicator, Is.EqualTo( 5 ) );
+1
source

, @dave thieben. , , .

, Dave, .

var kernel = new StandardKernel();
kernel.Bind<FooBar>().ToSelf().InSingletonScope();
kernel.Bind<IFoo>().ToMethod(ctx => ctx.Kernel.Get<FooBar>());
kernel.Bind<IBar>().ToMethod(ctx => ctx.Kernel.Get<FooBar>());

, . .

"" .

var kernel = new StandardKernel();
kernel.Bind<FooBar>().ToSelf()
    .Forward().As<IFoo>().As<IBar>()
         .InSingletonScope();

public interface IBindingForwardSyntax<T> : IBindingWhenInNamedWithOrOnSyntax<T>
{
    IBindingForwardSyntax<T> As<TService>();
}

public class BindingForwardBuilder<T> 
    : BindingBuilder<T>, IBindingForwardSyntax<T>
{
    public BindingForwardBuilder(IBinding binding, IKernel kernel) 
        : base(binding, kernel) { }

    public IBindingForwardSyntax<T> As<TForwardedType>()
    {
        Kernel.Bind<TForwardedType>().ToMethod(ctx =>
        {
            var provider = Binding.GetProvider(ctx);
            if (!typeof(TForwardedType).IsAssignableFrom(provider.Type))
            {
                string message = string.Format(
                     "Invalid binding between '{0}' and '{1}'",
                         typeof(TForwardedType), typeof(T));
                throw new InvalidOperationException(message);
            }

            return (TForwardedType)ctx.Kernel.Get(typeof(T));
        });

        return this;
    }
}

, .

public static class BindingWhenInNamedWithOrOnSyntaxExtensions
{
    public static IBindingForwardSyntax<T> Forward<T>(
        this IBindingWhenInNamedWithOrOnSyntax<T> syntax)
    {
        return new BindingForwardBuilder<T>(syntax.Binding, syntax.Kernel);
    }
}

, . . : . , , .

0

Source: https://habr.com/ru/post/1769018/


All Articles