2011-07-21 8 views
17

Proszę wybaczyć mojej niewiedzy, ale jestem nowy w IOC i NinJect. Szukałem wysokich i niskich dla łatwych w zrozumieniu rozwiązań, ale jak dotąd omijali mnie.Ninject - konstruktory wiążące z argumentami/ciąg połączenia Entity Framework

tej pory mam następujące i wszystkie prace zgodnie z oczekiwaniami:

private class StandardModule : NinjectModule 
    { 
     public override void Load() 
     { 
     Bind<ILog>().To<NLogLogger>(); // Use NLog 
     Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>(); 
     } 
    } 

MyEntityFrameWorkRepository następnie tworzy własny EF DbContext poprzez ciąg połączenia zadeklarowanej w app/web.config:

public class MyDbContext : DbContext 
{ 
    public MyDbContext() : base("MyAppConfig") 
    { 
    } 
    ........ 
} 

JEDNAK !! Moim celem jest coś takiego - Zdaję sobie sprawę z tego składnia to „nonsens” (i myślę może muszę MKOl MyDbConext też), ale mam nadzieję, że „pseudo-kod” oddaje moje pragnienie:

private class StandardModule : NinjectModule 
{ 
    public override void Load() 
    { 
    Bind<ILog>().To<NLogLogger>(); // Use NLog 

    string mySqlConnectionString = MyApp.GetCommandLineArgument("sqlconn"); // "Data Source=..." 
    Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>(mySqlConnectionString); 
    } 
} 

................. 

public class MyDbContext : DbContext 
{ 
    public MyDbContext(string sqlConnectionString) : 
     base(sqlConnectionString) // will accept a standard SQL connection string 
    { 
    } 
    ........ 
} 

Byłbym wdzięczny za opinie ekspertów IOC/NinJect, ponieważ jestem pewien, że każdy "wzór" może być bardzo przydatny w innych sytuacjach.

Odpowiedz

21

Możesz użyć metody .WithConstructorArgument(), aby określić argumenty konstruktora. Pierwszy argument powinien być nazwą parametru konstruktora.

public class StandardModule : NinjectModule 
{ 
    public override void Load() 
    { 
     string connectionString = "..."; 
     Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>() 
      .WithConstructorArgument("sqlConnectionString", connectionString); 
    } 

}

+0

TY tak wiele! ... Widziałem tę konstrukcję podczas moich poszukiwań, ale z jakiegoś powodu byłem zawsze (omyłkowo) zaniepokojony "zakresem" "connectionString" ... ale twój zwięzły przykład jasno ilustruje, że jest to tylko wartość _ wiążąca, która jest ważny. – JcMaltaDev

+0

Czy istnieje sposób, aby to zrobić bez magicznego łańcucha lub tak, aby ninject wiedział, które przeciążenie, ale decyduje, gdzie zdobyć wartości? – Maslow

+1

@Maslow Nie sądzę, że możesz to zrobić w wersji 2.2 (ale nie wierz mi na słowo). Jednak powinieneś przeczytać ten [post na blogu] (http://www.planetgeek.ch/2011/05/28/ninject-constructor-selection-preview/), który omawia nadchodzące zmiany. – mrydengren

3

Nowsze wersje Ninject pozwalają pozbyć magicznych ciągów w wiążącej definicji. Coś takiego:

public class StandardModule : NinjectModule 
{ 
    public override void Load() 
    { 
     string connectionString = "..."; 
     Bind<IMyEntityFrameWorkRepository() 
      .ToConstructor(_ => new MyEntityFrameWorkRepository(connectionString); 
    } 
} 

Dla wiązań z udziałem typów generycznych (np wiążą ISomeService<T> do SomeService<T> i wiązania powinny być wykonywane dla wszystkich możliwych typów na raz), ToConstructor nie mogą być używane (wymagany jest nowy wyrażenie), więc WithConstructorArgument szczątki najprostsze podejście. Np .:

Bind(typeof(ISomeService<>)) 
    .To(typeof(SomeService<>)) 
    .WithConstructorArgument("someParam", "someValue");