使用Unity,如何注册泛型的类型映射?

时间:2013-09-18 19:18:11

标签: entity-framework unity-container repository-pattern separation-of-concerns

我正在尝试实现repository solution for Entity Framework,但我无法使用Unity注册包含泛型的类型。

假设:

    // 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;
    }

我需要将IRepository的类型映射注册到Repository。但是这种映射的Unity语法有问题。

我试过以下但没有运气:

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

修改

基于@Steven响应,我现在有以下实现:

// 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<>));

1 个答案:

答案 0 :(得分:16)

您正尝试执行以下操作:

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

这通常会有效,但在这种情况下不会有诀窍,因为IRepository<TEntity>有一个通用参数而Repository<TEntity, TContext>有两个,而Unity(显然)可以&#39 ;猜猜它应该为TContext填写什么类型。

你需要的是:

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

换句话说,您希望将Repository<TEntity, TContext>作为部分开放泛型类型(填入一个参数)提供。不幸的是,C#编译器不支持这一点。

但即使C#支持这一点,Unity也不支持部分开放泛型类型。事实上,大多数IoC库eworks都不支持这一点。对于支持它的one library,您仍然需要执行以下操作(讨厌的事情)来创建部分开放泛型类型:

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

有一个简单的技巧可以解决这个问题:使用一个泛型类型定义一个派生类:

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

现在我们可以轻松注册这个开放的泛型类型:

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