How to register open generic types, closed generic types and decorate as with autofac?

I use Autofac as my IoC container. I have:

  • IRepository<> , my repository interface;
  • DbContextRepository<> - general repository implementation using EntityFramework DbContext;
  • Some private types of repositories inside the assembly, for example PersonRepository : DbContextRepository<Person> ;
  • And RepositoryDecorator<> , which adorns my repositories with some standard optional behavior;

I use autofac to register them like this:

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

I am trying to do the following:

  • register DbContextRepository<> as a general implementation of IRepository<> ;
  • then register closed type repositories so that they can overload the previous registration when necessary;
  • Then decorate them both, so when I ask the container to allow IRepository, it gives me a RepositoryDecorator with the correct IRepository implementation, since it is a registered DbContextRepository or private type.

When I try to resolve an IRepository<Product> that does not have a private type implementation, it returns a correctly decorated DbContextRepository.

But when I try to resolve an IRepository<Person> that has a private implementation, it also gives me a Decorated DbContextRepository instead of a Decorated PersonRepository.

+4
source share
1 answer

The problem of Named("repo2", typeof(IRepository<>)) does not do what you think. You need to explicitly specify the type for the type being checked.

 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(); 
+6
source

Source: https://habr.com/ru/post/1387202/


All Articles