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).

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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);

Method 2

What I’m using (with Ninject 3 now) is a little different but it works for me.
I create an array of dependencies and let them decide if they accept to handle the request or not. For example if I had this case

public enum FileFormat
{
    Pdf,
    Word,
    Excel,
    Text,
    Tex,
    Html
}

public interface IFileWriter
{
    bool Supports(FileFormat format)

    ...
}

public class FileProcessor
{
    FileProcessor(IFileWriter[] writers)
    {
        // build a dictionary with writers accepting different formats 
        // and choose them when needed
    }
}

public class MyModule : NinjectModule
{
     public override void Load()
     {
         ...

         Bind<IFileWriter>().To<PdfFileWriter>();
         Bind<IFileWriter>().To<WordFileWriter>();
         Bind<IFileWriter>().To<TexFileWriter>();
         Bind<IFileWriter>().To<TextFileWriter>();
         Bind<IFileWriter>().To<HtmlFileWriter>();
     }
}

I hope that helps!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x