Catalin
Catalin

Reputation: 11721

Ninject: bind interface to multiple implementations

I have an interface called IXMLModelsRepository, and i have a concrete implementation called XMLModelsRepository which simply reads from an XML file.

However, i want to improve the function, and i want to temporary cache the elements into a Dictionary<> list.

I don't want to modify the existing XMLModelsRepository, but i want to create a new class that adds the caching functionality on top.

How can i bind using Ninject an interface to two concrete implementations?

// the interface i am working with
public interface IXMLModelsRepository
{
    Product GetProduct(Guid entity_Id);
}

// concrete implementation that reads from XML document
public class XMLModelsRepository : IXMLModelsRepository
{
    private readonly XDocument _xDoc = LoadXMLDocument();

    public Product GetProduct(Guid entity_Id)
    {
        return _xDoc.Element("root").Elements("Product").Where(p => p.Attribute("Entity_Id").Value == entity_Id.ToString();
    }
}

// concrete implementation that is only responsable of caching the results
//    this is the class that i will use in the project,
//    but it needs a parameter of the same interface type
public class CachedXMLModelsRepository : IXMLModelsRepository
{
    private readonly IXMLModelsRepository _repository;
    public CachedXMLModelsRepository(
        IXMLModelsRepository repository)
    {
        _repository = repository;
    }

    private readonly Dictionary<Guid, Product> cachedProducts = new Dictionary<Guid, Product>();
    public Product GetProduct(Guid entity_Id)
    {
        if (cachedProducts.ContainsKey(entity_Id))
        {
            return cachedProducts[entity_Id];
        }

        Product product = _repository.GetProduct(entity_Id);
        cachedProducts.Add(entity_Id, product);

        return product;
    }
}

Upvotes: 3

Views: 1783

Answers (1)

faester
faester

Reputation: 15076

You can use the WhenInjectedExactlyInto construct.

kernel.Bind<IXMLModelsRepository >().To<CachedXMLModelsRepository>();
kernel.Bind<IXMLModelsRepository >().To<XMLModelsRepository>()
    .WhenInjectedExactlyInto(typeof(CachedXMLModelsRepository));

In the above example Ninject would use the cached instance for all lookups of the interface, but when constructing the cached repository, it would inject the non-cached object.

Upvotes: 5

Related Questions