20

Please forgive my ignorance, but I am very new to IOC and NinJect. I have searched for high and low for easily understandable solutions but so far they have eluded me.

So far I have the following and all works as expected:

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

MyEntityFrameWorkRepository then creates its own EF DbContext via a connection string declared in app/web.config:

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

HOWEVER!! My goal is something like this - I realise this syntax is "nonsense" (and I think I may have to IOC MyDbConext too) , but I hope the "pseudo-code" conveys my desire:

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
   {
   }
   ........
}

I would truly appreciate some feedback from IOC / NinJect experts, since I am sure any "pattern" can be very useful in other scenarios.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
JcMaltaDev
  • 1,344
  • 1
  • 9
  • 17

2 Answers2

25

You can use the .WithConstructorArgument() method to specify constructor arguments. The first argument should be the name of the constructor parameter.

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

}

Luke Hutton
  • 10,612
  • 6
  • 33
  • 58
mrydengren
  • 4,270
  • 2
  • 32
  • 33
  • TY so much! .. I had seen this construct during my searching, but for some reason I was always (mistakenly) concerned about the "scope" of 'connectionString' ... but your concise example clearly illustrates that it is only the _value_ at binding that is important. – JcMaltaDev Jul 21 '11 at 13:35
  • is there a way to do it without the magic string or so that ninject knows which overload but decides itself where to acquire the values? – Maslow Jan 12 '12 at 22:41
  • 1
    @Maslow I don't think you can do it in Ninject 2.2 (but don't take my word for it). However, you should read this [blog post](http://www.planetgeek.ch/2011/05/28/ninject-constructor-selection-preview/) which discusses upcoming changes. – mrydengren Jan 13 '12 at 06:30
  • 1
    @mrydengren Is it possible to call `WithConstructorArgument` multiple times for multiple constructor parameters? – The Muffin Man Oct 03 '13 at 04:21
  • @The Muffin Man Yes it is! – BatteryBackupUnit Oct 09 '14 at 19:33
5

Newer versions of Ninject allow to get rid of magic strings in the binding definition. Something like this:

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

For bindings involving generic types (e.g. bind ISomeService<T> to SomeService<T> and binding should be performed for all possible types at once), ToConstructor cannot be used (a new expression is required), so WithConstructorArgument remains the simplest approach. E.g.:

Bind(typeof(ISomeService<>))
    .To(typeof(SomeService<>))
    .WithConstructorArgument("someParam", "someValue");
Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164