Как зарегистрировать открытые универсальные типы, закрытые универсальные типы и декорировать оба с помощью autofac? - PullRequest
4 голосов
/ 20 декабря 2011

Я использую Autofac в качестве контейнера IoC.У меня есть:

  1. IRepository<>, мой интерфейс хранилища;
  2. DbContextRepository<>, общая реализация хранилища с использованием EntityFramework's DbContext;
  3. Некоторые репозитории закрытых типов внутри сборки, скажем PersonRepository : DbContextRepository<Person>;
  4. и RepositoryDecorator<>, который украшает мои репозитории некоторым стандартным дополнительным поведением;

Я использую autofac для их регистрации следующим образом:

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>, который не имеет реализации закрытого типа, он корректно возвращает Decorated DbContextRepository.

Но когда я пытаюсь разрешить IRepository<Person>, который имеет реализация закрытого типа, она также дает мне Decorated DbContextRepository вместо Decorated PersonRepository.

1 Ответ

7 голосов
/ 21 декабря 2011

Проблема в том, что 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...