jgauffin
jgauffin

Reputation: 101150

Resolve generic service

I got the following service:

IRepository<TEntity, TPrimaryKey>

..for which I've created an implementation defined as:

Repository<TEntity, TPrimaryKey>.

How do I register it in autofac so that I can resolve it as:

IRepository<User, int>

Upvotes: 1

Views: 392

Answers (2)

Steven
Steven

Reputation: 172646

As an alternative to your own solution, you might try defining a factory for creating new repository instances:

public interface IRepositoryFactory
{
    IRepository<TEntity, TPrimaryKey> 
        CreateRepository<TEntity, TPrimaryKey>();

    // Perhaps other overloads here
}

internal class RepositoryFactory : IRepositoryFactory
{
    public IContainer Container { get; set; }

    public IRepository<TEntity, TPrimaryKey> 
        CreateRepository<TEntity, TPrimaryKey>()
    {
        return container.Resolve<Repository<TEntity, TPrimaryKey>>();
    }
}

You can register the RepositoryFactory as follows:

builder.Register(c => new RepositoryFactory() { Container = c })
    .As<IRepositoryFactory>()
    .SingleInstance();

Now you can declare IRepositoryFactory as constructor argument and create new instances. Look for instance at this ProcessUserAccountUpgradeCommand class that uses dependency injection for its dependencies:

public ProcessUserAccountUpgradeCommand : ServiceCommand
{
    private readonly IRepositoryFactory factory;

    ProcessUserAccountUpgradeCommand(IRepositoryFactory factory)
    {
        this.factory = factory;
    }

    protected override void ExecuteInternal()
    {
        // Just call the factory to get a repository.
        var repository = this.factory.CreateRepository<User, int>();

        User user = repository.GetByKey(5);
    }
}

While this might seem a bit cumbersome to use a factory instead of getting a repository directly, your design will communicate clearly that a new instance is retrieved (because you call the CreateRepository method). Instances returned from a IoC container are normally expected to have a long life.

Another tip: You might want to refactor the use of the primary key type away. It would be cumbersome to always ask for repositories of <User, int> instead of just <User> repositories. Perhaps you find a way to abstract the primary key away inside the factory.

I hope this helps.

Upvotes: 0

jgauffin
jgauffin

Reputation: 101150

builder.RegisterGeneric(typeof (Repository<,>)).As(typeof (IRepository<,>));

I love autofac.

Upvotes: 4

Related Questions