cwiederspan
cwiederspan

Reputation: 95

Injecting Different Implementations of Same Interface in ASP.NET 5

In ASP.NET 5, I have an IRepository interface that I used to access some databases, like this:

public interface IRepository {
    IQueryable<T> QueryItems(string sql);
}

public class Repository : IRepository {

    private readonly string ConnectionString;

    public Repository(string connStr) {
        // Save the injected connection string
        this.ConnectionString = connStr;
    }

    public IQueryable<T> QueryItems(string sql) {
        // Implementation ignored here
    }
}

In my Startup.cs class, I am registering the IoC/DI like this:

services.AddTransient<IRepository>(s => new Repository("DUMMY_CONNSTR"));

That all works fine if I only have one connection string. However, how can I register and subsequently inject the correct IRepository if I use the Repository to connect to 2+ different databases with different connection strings?

services.AddTransient<IRepository>(s => new Repository("DUMMY_CONNSTR"));
services.AddTransient<IRepository>(s => new Repository("DIFFERENT_CONNSTR"));

In older IoC/DI systems, I would have use "named" implementations that could be resolved with something like a [Dependency("DUMMY")] attribute on the constructor parameter.

Any help would be appreciated.

Upvotes: 2

Views: 2563

Answers (2)

Jeff Ogata
Jeff Ogata

Reputation: 57783

You can substitute StructureMap or Autofac for the default DI container (see my blog post for detailed instructions). Both support "named" interface registration (StructureMap named instances and Autofac named and keyed services).

Additionally, if you target dnx451, you can use Autofac's WithKey attribute. Using the Visual Studio sample project from the blog post, add the following dependency in project.json:

"frameworks": {
  "dnx451": {
    "dependencies": {
      "Autofac.Extras.AttributeMetadata": "4.0.0"
    }
  }
},

Given a test class with the following constructor:

public MyClass([WithKey("logging")] IRepository repository)
{
    Repository = repository;
}

you would register everything in ConfigureServices (note the use of WithAttributeFilter():

containerBuilder.Register(c => new Repository("DEFAULT_CONNSTR")).Keyed<IRepository>("default");
containerBuilder.Register(c => new Repository("LOGGING_CONNSTR")).Keyed<IRepository>("logging");

containerBuilder.RegisterType<MyClass>().WithAttributeFilter();

Upvotes: 0

aidrivenpost
aidrivenpost

Reputation: 1943

There are a few approach that you can take one is to inject a factory and base on the specific criteria you can produce a repository, the other approach is use a Dispatcher that also produce the repository base on the criteria, below is a question that I ask with the same problem. The question below have both approach but they were codding a beta version of .net core

See this question for reference and code

Upvotes: 1

Related Questions