Ninject conditional binding based on property value

前端 未结 2 1273
栀梦
栀梦 2021-01-19 02:07

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

相关标签:
2条回答
  • 2021-01-19 02:21

    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);
    
    0 讨论(0)
  • 2021-01-19 02:23

    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!

    0 讨论(0)
提交回复
热议问题