Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Unity, how do you register type mappings for generics?

I'm trying to implement a repository solution for Entity Framework but I am having trouble registering the types that include generics using Unity.

Given:

    // IRepository interface
    public interface IRepository<TEntity>
    {
        // omitted for brevity
    }

    // Repository implementation
    public class Repository<TEntity, TContext> : IRepository<TEntity>, IDisposable 
            where TEntity : class
            where TContext : DbContext
    {
        // omitted for brevity
    }

    // service layer constructor
    public MyServiceConstructor(IRepository<Account> repository)
    {
        _repository = repository;
    }

I need to register the type mapping for IRepository to Repository. but I'm having trouble with the Unity syntax for this kind of mapping.

I have tried the following with no luck:

container.RegisterType<IRepository<>, typeof(Repository<,>)>();
container.RegisterType<typeof(IRepository<>), Repository<,>>();

EDIT

Based, on @Steven response I have the following implementation now:

// UnityRepository implementation   
public class UnityRepository<TEntity> : Repository<TEntity, MyDbContextEntities>
        where TEntity : class
{
    public UnityRepository() : base(new MyDbContextEntities()) { }
}

// Unity bootstrapper
container.RegisterType(typeof(IRepository<>), typeof(UnityRepository<>));
like image 311
Mark Erasmus Avatar asked Sep 18 '13 19:09

Mark Erasmus


People also ask

How do I register a type with Unity container?

Before Unity resolves the dependencies, we need to register the type-mapping with the container, so that it can create the correct object for the given type. Use the RegisterType() method to register a type mapping. Basically, it configures which class to instantiate for which interface or base class.

What is UnityContainer c#?

The Unity Container (Unity) is a full featured, extensible dependency injection container. It facilitates building loosely coupled applications and provides developers with the following advantages: Simplified object creation, especially for hierarchical object structures and dependencies.


1 Answers

You are trying to do the following:

container.RegisterType(typeof(IRepository<>), typeof(Repository<,>));

This would normally work, but won't do the trick in this case, since there is IRepository<TEntity> has one generic argument and Repository<TEntity, TContext> has two, and Unity (obviously) can't guess what type it should fill in for TContext.

What you need is this:

container.RegisterType(
    typeof(IRepository<>),
    typeof(Repository<, MyDbContextEntities>));

In other words, you'd want to supply the Repository<TEntity, TContext> as a partial open generic type (with one parameter filled in). Unfortunately, the C# compiler does not support this.

But even if the C# did support this, Unity doesn't support partial open generic types. In fact most IoC libraries eworks don't support this. And for that one library that does support it, you would still have to do the following (nasty thing) to create the partial open generic type:

Type myDbContextEntitiesRepositoryType =
    typeof(Repository<,>).MakeGenericType(
        typeof(Repository<,>).GetGenericParameters().First(),
        typeof(MyDbContextEntities));

There's a easy trick work around to get this to work though: define a derived class with one generic type:

// Special implementation inside your Composition Root
public class UnityRepository<TEntity> : Repository<TEntity, MyDbContextEntities>
        where TEntity : class
{
    public UnityRepository([dependencies]) : base([dependencies]) { }
}

Now we can easily register this open generic type:

container.RegisterType(typeof(IRepository<>), typeof(UnityRepository<>));
like image 99
Steven Avatar answered Oct 01 '22 16:10

Steven