Domanda

di Ok Dipendenza Ninja, ecco uno per te ...

Voglio cambiare il modo in cui Ninject costruisce una dipendenza in base al tipo che sto chiedendo dal Kernel.

Ho una classe DbConnectionFactory con i seguenti costruttori:

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

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

Per il "default" di legame, voglio Ninject utilizzare il costruttore senza parametri:

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

Alcune classi nel mio codice bisogno Ninject per fornire il paramter connectionString. Ho cercato di impostare la rilegatura in questo modo:

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

Tuttavia, ho sempre e solo ottenere Ninject utilizzare il costruttore di default.

Devo mancare qualcosa di ovvio!

È stato utile?

Soluzione

Sembra come se ci fosse un po 'troppi strati qui. Perché avete bisogno di un DatabaseGateway? Perché non utilizza le fabbriche del provider ADO.NET per creare collegamenti (è possibile cablare questi attraverso Ninject pure) di gestire direttamente le connessioni? O meglio ancora, con il modello repository usare qualcosa come NHibernate e utilizzare questo per mappare gli oggetti?

Indipendentemente da ciò, come circa sempre utilizzando il costruttore più a lungo e alternativamente passando sia MyDatabase.ConnectionString o MyOtherDatabase.ConnectionString a seconda della situazione? Si potrebbe utilizzare un provider come qui e qui ma cerco di evitarli se non assolutamente necessario:

  1. Definire due nuovi attributi

    public class DefaultDatabaseAttribute : Attribute {}
    public class OtherDatabaseAttribute : Attribute {}
    
  2. Decorare gli argomenti DatabaseGateway con gli attributi appropriati nel costruttore

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

    e il vostro fornitore sarà simile:

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

È possibile espandere questo modello per aggiungere ulteriori attributi deciso se la fabbrica deve anche essere restituito nel DatabaseGateway.

E 'imbarazzante, ma può essere la migliore che puoi fare dato il numero di strati coinvolti.

Altri suggerimenti

può aiutare pure. Come ha detto Jeff, ti consigliamo di utilizzare il With.Parameters.ConstructorArgument (). È possibile passare più argomenti continuando a catena ConstructorArgument o utilizzando un dizionario. Spero che questo aiuta!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top