0

How to bind classes with required connection string in constructor using Ninject?

Here are the classes that I am using:

AppService class:

using SomeProject.LayerB;

namespace SomeProject.LayerA;
{
    public class AppService
    {
        private readonly ISomeRepository someRepository;

        public LocationManagementService(ISomeRepository someRepository)
        {
            this.someRepository = someRepository;
        }

        // other codes ...
    }  
}

SomeRepository class:

namespace SomeProject.LayerB;
{
    public class SomeRepository : ISomeRepository
    {
        private readonly SomeDbContext context;

        public SomeRepository(SomeDbContext context)
        {
            this.context = context;
        }

        // other codes ...
    }
}

SomeDbContext class:

namespace SomeProject.LayerB;
{
    public class SomeDbContext : DbContext
    {
        public SomeDbContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {
        }

        // other codes ...
    }  
}

Then, I use a Ninject module containing the following code:

namespace SomeProject.LayerC;  
{
    public class SomeModule : NinjectModule
    {
        public override void Load()
        {
            Bind<ISomeRepository>().To<SomeRepository>();

            // My problem is on this part.. I want to provide the connection string on the
            // main program, not here on this class.
            // Bind<SomeDbContext>().ToSelf().WithConstructorArgument("nameOrConnectionString", "the connection string I want to inject");
        }
    } 
} 

Main program:

using SomeProject.LayerA;
using SomeProject.LayerC;

namespace SomeProject.LayerD;
{
    public class MainProgram
    {
        public MainProgram()
        {
            IKernel kernel = new StandardKernel(new SomeModule());

            AppService appService = kernel.Get<AppService>();
        }
    }  
}

NOTE: The only layer that main program can reference is LayerA where AppService class is located and as well as LayerC where the ninject module is found.

devpro101
  • 338
  • 1
  • 3
  • 13
  • 1
    The error here is that use your container's auto-wiring capabilities to build up a framework type (your `SomeDbContext`). As described [here](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97#Framework-types), you should register that `SomeDbContext` using a lambda so that your code calls `SomeDbContext`'s constructor. – Steven Jul 25 '15 at 11:19
  • Thanks for your reply, I'll read that post right now ^_^ – devpro101 Jul 25 '15 at 11:33

1 Answers1

0

Add a Configuration class like this:

public class Config
{
    public static string ConnectionString { get; set; }
}

and in your ninject module write this:

Bind<SomeDbContext>().ToSelf()
   .WithConstructorArgument("nameOrConnectionString", 
       c => Config.ConnectionString);  

then in your main method you could write following:

public class MainProgram
{
    public MainProgram()
    {
        IKernel kernel = new StandardKernel(new SomeModule());
        Config.ConnectionString = "The connection string";
        AppService appService = kernel.Get<AppService>();
    }
}  

Update:

You can use ninject to locate config class also if you don't want use static methods:

class Config2
{
    public string ConnectionString { get; set; }
}

in module:

Bind<Config2>().ToSelf().InSingletonScope();
Bind<SomeDbContext>().ToSelf()
   .WithConstructorArgument("nameOrConnectionString",
       c=>c.Kernel.Get<Config2>().ConnectionString);

in main:

IKernel kernel = new StandardKernel(new SomeModule());
var conf = kernel.Get<Config2>();
conf.ConnectionString = "The connection string";
AppService appService = kernel.Get<AppService>();
Sam FarajpourGhamari
  • 14,601
  • 4
  • 52
  • 56
  • Thanks for your quick reply. If I use your method, then my connection string would come from a class rather than from the app.config or web.config file..can I still benefit from having a secured connection string like what I can get from encrypting the connection string using the app.config or web.config? I'm sorry for my late reply, I fell asleep a while ago waiting for answers here on SO because I haven't got any sleep from last night trying to solve this problem hehe... – devpro101 Jul 25 '15 at 11:25
  • Also, If I use a separate class for my connection string, I think I would put it on a separate assembly as well because my current setup is that the assembly where my Main program is located is my composition root... which means my main program is referencing the assembly where my ninject modules are located... – devpro101 Jul 25 '15 at 11:32
  • 1
    I have tried to show you how you can inject constructer's parameter with an other class. So you could write own provider to get the connection string whatever you want. If you don't get the point tell me to write an example. – Sam FarajpourGhamari Jul 25 '15 at 11:41
  • Ahh you mean using a provider? I think I get what your trying to tell me now. Thanks, I'll post an update later ^_^ – devpro101 Jul 25 '15 at 11:56
  • My code works now, I ended up using second method instead because I realized I don't need a provider for my current setup. Thank you so much, I really needed a little push to the right direction here hehe, thanks again ^_^ – devpro101 Jul 25 '15 at 12:56