Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject : Constructor parameter

I am using Ninject together with ASP.NET MVC 4. I am using repositories and want to do constructor injection to pass in the repository to one of the controllers.

This is my Repository interface:

public interface IRepository<T> where T : TableServiceEntity
{
    void Add(T item);
    void Delete(T item);
    void Update(T item);
    IEnumerable<T> Find(params Specification<T>[] specifications);
    IEnumerable<T> RetrieveAll();
    void SaveChanges();
}

The AzureTableStorageRepository below is an implementation of IRepository<T>:

public class AzureTableRepository<T> : IRepository<T> where T : TableServiceEntity
{
    private readonly string _tableName;
    private readonly TableServiceContext _dataContext;

    private CloudStorageAccount _storageAccount;
    private CloudTableClient _tableClient;

    public AzureTableRepository(string tableName)
    {
        // Create an instance of a Windows Azure Storage account
        _storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);

        _tableClient = _storageAccount.CreateCloudTableClient();
        _tableClient.CreateTableIfNotExist(tableName);
        _dataContext = _tableClient.GetDataServiceContext();
        _tableName = tableName;
    }

Note the tableName parameter needed because I was using a generic table repository to persist data to Azure.

And finally I have the following controller.

public class CategoriesController : ApiController
{
    static IRepository<Category> _repository;

    public CategoriesController(IRepository<Category> repository)
    {
        if (repository == null)
        {
            throw new ArgumentNullException("repository");
        }

        _repository = repository;
    }

Now I want to inject a repository into the controller. So I have created a module that contains the bindings:

/// <summary>
/// Ninject module to handle dependency injection of repositories
/// </summary>
public class RepositoryNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository<Category>>().To<AzureTableRepository<Category>>();
    }
}

The loading of the module is done in the NinjectWebCommon.cs

/// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        // Load the module that contains the binding
        kernel.Load(new RepositoryNinjectModule());

        // Set resolver needed to use Ninject with MVC4 Web API
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
    } 

The DependencyResolver was created because Ninject's DependencyResolver implements System.Web.Mvc.IDependencyResolver and this cannot be assigned to GlobalConfiguration.Configuration of the WebApi Application.

So with all this in place, the Ninject part is actually injecting the right type in the Controller but Ninject cannot inject the tableName parameter in the constructor of AzureTableRepository.

How would I be able to do this in this case? I have consulted a lot of articles and the ninject documentation to see how I could use parameters, but I cannot seem to get it working.

Any help would be appreciated.

like image 939
Kenny Saelen Avatar asked Dec 15 '12 14:12

Kenny Saelen


1 Answers

I'd use the WithConstructorArgument() method like...

Bind<IRepository<Category>>().To<AzureTableRepository<Category>>()
    .WithConstructorArgument("tableName", "categories");

The rest of the repository design is probably another question. IMHO It seems like a big no no to create a table or do any heavy lifting in a ctor.

like image 156
dotjoe Avatar answered Nov 06 '22 13:11

dotjoe