2009-07-19 18 views
2

Ok Abhängigkeit Ninjas, hier ist für Sie ...Ninject: Howto Setup Bindungen basierend auf Abhängigkeitskette

ich den Weg Ninject baut eine Abhängigkeit von der Art der Grundlage geändert werden soll ich vom Kernel anfordert.

Ich habe eine DbConnectionFactory Klasse mit den folgenden Konstruktoren:

public DbConnectionFactory() 
     : this(MyDatabase.ConnectionString) 
    { 
    } 

    public DbConnectionFactory(string connectionString) 
     : this(DbProviderFactories.GetFactory("System.Data.SqlClient"), connectionString) 
    { 
    } 

Für die "default" Bindung, ich Ninject den parameterlosen Konstruktor verwenden möchten:

 this.Bind<IDbConnectionFactory>().To<DbConnectionFactory>(); 

Bestimmte Klassen in meinem Code Notwendigkeit Ninject, um den ConnectionString-Parameter zu liefern. Ich habe versucht, die Bindung wie folgt einzurichten:

 this.Bind<IDbConnectionFactory>().To<DbConnectionFactory>().Only(
      When.Context.InstanceOf(typeof(IRepository))).WithArgument(
      "connectionString", MyOtherDatabase.ConnectionString); 

Allerdings bekomme ich nur Ninject den Standardkonstruktor zu verwenden.

Ich muss etwas offensichtlich fehlen!

Antwort

3

Es klingt, als ob hier ein bisschen zu viele Schichten sind. Warum brauchst du ein DatabaseGateway? Warum verwenden Sie die ADO.NET-Provider-Factorys nicht zum Erstellen von Verbindungen (Sie können diese auch über Ninject verbinden), um Ihre Verbindungen direkt zu verwalten? Oder noch besser, mit dem Repository-Muster verwenden Sie etwas wie NHibernate und verwenden Sie dies, um Objekte zuzuordnen?

Unabhängig davon, wie Sie immer den längeren Konstruktor verwenden und je nach Situation abwechselnd MyDatabase.ConnectionString oder MyOtherDatabase.ConnectionString übergeben? Sie könnten einen Anbieter verwenden, wie here beschrieben und here aber ich versuche, sie zu vermeiden, wenn es nicht unbedingt notwendig:

  1. definieren zwei neue Attribute

    public class DefaultDatabaseAttribute : Attribute {} 
    public class OtherDatabaseAttribute : Attribute {} 
    
  2. Dekorieren Sie die DatabaseGateway Argumente mit den entsprechenden Attributen in den Konstruktor

    public class OneRepository : IRepository 
    { 
        public OneRepository([DefaultDatabase]DatabaseGateway factory) 
        { 
        } 
    } 
    
    public class TwoRepository : IRepository 
    { 
        public TwoRepository([OtherDatabase]DatabaseGateway factory) 
        { 
        } 
    } 
    

    und Ihren Provider würde wie folgt aussehen:

    public class DatabaseGatewayProvider : SimpleProvider<DatabaseGateway> 
    { 
         protected override DatabaseGateway CreateInstance(Ninject.Core.Activation.IContext context) 
         { 
          IDbConnectionFactory factory; 
          if (context.Member.IsDefined(typeof(DefaultDatabaseAttribute), false)) 
          { 
           factory = context.Kernel.get<IDbConnectionFactory>(With.Parameters.ConstructorArgument("connectionString", MyDatabase.ConnectionString))); 
          } 
          else if (context.Member.IsDefined(typeof(OtherDatabaseAttribute), false)) 
          { 
           factory = context.Kernel.get<IDbConnectionFactory>(With.Parameters.ConstructorArgument("connectionString", MyOtherDatabase.ConnectionString))); 
          } 
    
          return new DatabaseGateway(factory); 
         } 
    } 
    

können Sie dieses Modell erweitern zusätzliche Attribute entschieden hinzuzufügen, wenn das Werk selbst in der DatabaseGateway zurückgegeben werden muss.

Es ist peinlich, aber möglicherweise das Beste, was Sie tun können, angesichts der Anzahl der beteiligten Schichten.

1

Diese article kann Ihnen auch helfen. Wie Jeff schon sagte, möchten Sie With.Parameters.ConstructorArgument() verwenden. Sie können mehrere Argumente übergeben, indem Sie ConstructorArgument oder ein Dictionary weiter verketten. Hoffe das hilft!

Verwandte Themen