Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject conditional binding based on property value

I am having trouble defining bindings using ninject.

I am in a standard ASP.NET WebForms application. I have defined an http handler to Inject dependencies in pages and controls (Property injection).

Here is what I am trying to do:

I am creating a custom combobox usercontrol. Based on the value of an enum on that combobox, I want to be able to Inject a different object in a property (What I am trying to do is a bit more involved than that, but answer to this should be enough to get me going).

like image 904
Martin Avatar asked Mar 28 '11 13:03

Martin


1 Answers

A conditional binding based on a property value isn't a good design and isn't even possible (at least for constructor injection) as dependencies are normally created before the object receiving them. What if the property is changed later? The preferable way is to inject a factory or factory method that requests the instance from Ninject and exchange the strategy on initialization and property value change internally.

public enum EntityType { A,B } 
public class MyControl : UserControl
{
    [Inject]
    public Func<EntityType, IMyEntityDisplayStrategy> DisplayStrategyFactory 
    { 
        get { return this.factory; }
        set { this.factory = value; this.UpdateEntityDisplayStrategy(); }
    }

    public EntityType Type 
    { 
        get { return this.type; } 
        set { this.type = value; this.UpdateEntityDisplayStrategy(); };
    }

    private UpdateEntityDisplayStrategy()
    {
        if (this.DisplayStrategyFactory != null)
            this.entityDisplayStrategy = this.DisplayStrategyFactory(this.type);
    }
}

Bind<Func<EntityType, IMyEntityDisplayStrategy>>
    .ToMethod(ctx => type => 
         type == ctx.kernel.Get<IMyEntityDisplayStrategy>( m => 
             m.Get("EntityType", EntityType.A));
Bind<IMyEntityDisplayStrategy>.To<AEntityDisplayStrategy>()
    .WithMetadata("EntityType", EntityType.A)
Bind<IMyEntityDisplayStrategy>.To<BEntityDisplayStrategy>()
    .WithMetadata("EntityType", EntityType.B)

Alternatively add an activation action and inject the dependency manually. But be aware that changing the constraint property will lead to an inconsistent state.

OnActivation((ctx, instance) => 
    instance.MyStrategy = ctx.Kernel.Get<MyDependency>(m => 
        m.Get("MyConstraint", null) == instance.MyConstraint);
like image 178
Remo Gloor Avatar answered Nov 15 '22 11:11

Remo Gloor