2016-07-27 28 views
1

Ich verwende Ninject, um Abhängigkeiten zu injizieren. Ich habe die folgende Klassenstruktur:C# Ninject Parameter basierte Bindung

public interface IClass 
{ 
} 

public class Class: IClass 
{ 
public virtual void Method(Object context) 
{ 
    -------- 
} 
} 

public class Class1: IClass 
{ 
public override void Method(Object context) 
{ 
    -------- 
} 
} 

public class Class2: IClass 
{ 
public override void Method(Object context) 
{ 
    -------- 
} 
} 

context enthält - HasBilling, HasPayment Eigenschaften zusammen mit anderen mehr Eigenschaften.

Method() mithilfe von Factorymuster aufgerufen wird:

public interface IClassFactory 
    { 
     IClass CreateClass(); 
    } 

_classFactory.CreateClass().Method(....) 

Also, wenn der Parameter HasBilling zu true entspricht dann habe ich Method() von Class1 Implementierung aufzurufen, in ähnlicher Weise, wenn HasPayment auf true entspricht, Method() von Class2 Implementierung muss sein namens.

Mit Ninject Bindung habe ich versucht, diese Bindungen, aber keiner ist:

Bind<IClass>().To<Class1>().When(x => x.Target.Member.Name.Contains("HasBilling").Equals(true)); 

dies versucht, aber kein Glück:

Bind<IClass>().To<Class1>().WithMetadata("HasBilling", true); 

Bitte kann jemand mir helfen, mit dem, was Bindungen muss eingestellt sein, um Class1, Class2 Methode (Method) basierend auf einem Parameterwert (HasBilling,HasPayment) aufzurufen.

Vielen Dank im voraus,

Danke, WH

Antwort

0

Wenn Ihr context notwendig ist, welche konkreten Typ zu bestimmen dann laden Sie es passieren entweder an Ihre konkreten Klassen oder in die Fabrik benötigen . AFAIK gibt es keine Möglichkeit für Ninject, Ihre Aufrufkette zu untersuchen, um zu sagen, "Methode X wird aufgerufen werden, also muss ich diese Information verwenden, um zu bestimmen, welche konkrete Klasse zu verwenden ist".

Wenn Sie Ihre Fabrik, dieses Problem, weil sehr einfach ändern:

interface IClassFactory 
{ 
    IClass CreateClass(Object context) 
} 

class ClassFactory : IClassFactory 
{ 
    IClass CreateClass(Object context) 
    { 
     if (context.HasBilling) 
      return new Class1(); 

     // default case 
     return new Class2(); 
    } 
} 

Dann würden Sie verbrauchen:

IClassFactory classFactory; // injected 
object context; 

classFactory.CreateClass(context).Method(); 

Eine Alternative ist, ein Proxy-Muster zu verwenden. IClass bleibt gleich, weg mit IClassFactory. Stattdessen verwenden Sie einen Proxy:

public class ClassProxy : IClass 
{ 
    void Method(Object context) 
    { 
     if (context.HasBilling) 
      new Class1().Method(context); 
     else 
     //etc 
    } 
} 

In Ihrem kernal würden Sie diese verdrahten wie:

kernel.Bind<IClass>().To<ClassProxy>(); 

Sie auch brauchen würde, um sicherzustellen, dass Ihre Implementierungen nicht in den Kernel zu IClass gebunden. (So ​​stellen Sie sicher, dass es Sie gibt DO NOT haben kernel.Bind<IClass>().To<Class1>().

Wenn Sie die Vorteile von DI nehmen wollen für Ihre Implementierungsklassen, jedoch könnte man sie selbst bindable (kernel.Bind<Class1>().ToSelf()) machen und Ihr dann ClassProxy könnte sie als Abhängigkeiten nehmen:

class ClassProxy : IClass 
{ 
    private readonly Class1 _class1;  
    private readonly Class2 _class2; 

    public ClassProxy(Class1 class1, Class2 class2){ 
     _class1 = class1; 
     _class2 = class2; 
    } 

    void Method(object context) 
    { 
     if (context.HasBilling) 
      _class1.Method(context); 
    }