如何注册开放泛型类型,关闭泛型类型和装饰两者使用autofac

本文关键字:泛型类型 autofac 何注册 注册 | 更新日期: 2023-09-27 18:18:36

我使用Autofac作为我的IoC容器。我有:

  1. IRepository<>,我的仓库接口;
  2. DbContextRepository<>,一个使用EntityFramework的DbContext的库的通用实现;
  3. 程序集中的一些封闭类型存储库,例如PersonRepository : DbContextRepository<Person>;
  4. 和一个RepositoryDecorator<>,它用一些标准的额外行为装饰我的存储库;

我使用autoface来注册它们,像这样:

builder.RegisterGeneric(typeof(DbContextRepository<>))
            .Named("repo", typeof(IRepository<>));
builder.RegisterGenericDecorator(
                typeof(RepositoryDecorator<>),
                typeof(IRepository<>),
                fromKey: "repo");            
var repositorios = Assembly.GetAssembly(typeof(PersonRepository));
builder.RegisterAssemblyTypes(repositorios).Where(t => t.Name.EndsWith("Repository"))
          .AsClosedTypesOf(typeof(IRepository<>))
          .Named("repo2", typeof(IRepository<>))
          .PropertiesAutowired();
builder.RegisterGenericDecorator(
               typeof(RepositoryDecorator<>),
               typeof(IRepository<>),
               fromKey: "repo2");

我想做的是:

  1. 注册DbContextRepository<>作为IRepository<>的通用实现;
  2. 然后注册闭类型存储库,这样它们就可以在需要时重载之前的注册;
  3. 然后装饰它们,当我要求容器解析IRepository时,它给我一个RepositoryDecorator与IRepository的正确实现,它是一个DbContextRepository或已经注册的封闭类型。

当我尝试解决IRepository<Product>时,它没有封闭类型实现,它正确返回一个装饰的DbContextRepository。

但是当我试图解决IRepository<Person>,其中具有封闭类型实现时,它还给了我一个装饰的DbContextRepository,而不是一个装饰的PersonRepository。

如何注册开放泛型类型,关闭泛型类型和装饰两者使用autofac

问题是Named("repo2", typeof(IRepository<>))没有按照你的想法去做。您需要为正在扫描的类型显式指定类型。

static Type GetIRepositoryType(Type type)
{
    return type.GetInterfaces()
        .Where(i => i.IsGenericType
            && i.GetGenericTypeDefinition() == typeof(IRepository<>))
        .Single();
}
builder.RegisterAssemblyTypes(this.GetType().Assembly)
    .Where(t => t.IsClosedTypeOf(typeof(DbContextRepository<>)))
    .As(t => new Autofac.Core.KeyedService("repo2", GetIRepositoryType(t)))
    .PropertiesAutowired();