Question

Here is my problem. I have a presenter class, lets call it 'Presenter' that takes an IDataSource as a constructor argument. There are different implementations of the IDataSource interface. I would like to be able to pass some argument to Ninject and based on that argument one of several IDataSource implementations should by used. I've provided some sample code below. I think that my solution is really ugly and that there must be a smarter, cleaner way to do this. How are you guys solving this type of problem?

Here is my sample code

public class Presenter
{
    public Presenter(IDataSource dataSource)
    {
        DataSource = dataSource;
    }

    private IDataSource DataSource { get; set; }

    public List<string> GetData()
    {
        return DataSource.GetAll();
    } 
}

public class InMemoryDataSource : IDataSource
{
    public List<string> GetAll()
    {
        return new List<string> {"a", "b"};
    }
}

public class DbDataSource : IDataSource
{
    public List<string> GetAll()
    {
        return new List<string> { "1", "2" };
    }
}

public interface IDataSource
{
    List<string> GetAll();
}

public class Module : NinjectModule
{
    public override void Load()
    {
        Bind<Presenter>().To<Presenter>().Named("Db");
        Bind<Presenter>().To<Presenter>().Named("InMemory");
        Bind<IDataSource>().To<InMemoryDataSource>    ().WhenParentNamed("InMemory");
        Bind<IDataSource>().To<DbDataSource>().WhenParentNamed("Db");
    }
}

[Test]
public void Run()
    {
        using (var kernel = new StandardKernel(new Module()))
        {
            var p = kernel.Get<Presenter>(x => x.Name == "InMemory");

            foreach(var s in p.GetData())
            {
                Console.Out.WriteLine(s);
            }
        }
    }
Was it helpful?

Solution

This depends on what you want to do. I assume that you want to use a different db for testing than for production. In this case would create the module with the production configuration in mind and simply Rebind everything for testing:

public class Presenter
{
    public Presenter(IDataSource dataSource)
    {
        DataSource = dataSource;
    }

    private IDataSource DataSource { get; set; }

    public List<string> GetData()
    {
        return DataSource.GetAll();
    } 
}

public class InMemoryDataSource : IDataSource
{
    public List<string> GetAll()
    {
        return new List<string> {"a", "b"};
    }
}

public class DbDataSource : IDataSource
{
    public List<string> GetAll()
    {
        return new List<string> { "1", "2" };
    }
}

public interface IDataSource
{
    List<string> GetAll();
}

public class Module : NinjectModule
{
    public override void Load()
    {
        Bind<Presenter>().To<Presenter>();
        Bind<IDataSource>().To<DbDataSource>();
    }
}

[Test]
public void Run()
    {
        using (var kernel = new StandardKernel(new Module()))
        {
            kernel.Rebind<IDataSource>().To<InMemoryDataSource>();
            var p = kernel.Get<Presenter>();

            foreach(var s in p.GetData())
            {
                Console.Out.WriteLine(s);
            }
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top