Не удалось разрешить службу AutoFac Keyed с не работающим KeyFilterAttribute - PullRequest
0 голосов
/ 22 октября 2018

У меня есть общая реализация шаблона UnitOfWork, и эти объекты UnitOfWork являются зависимостями от моих классов обслуживания.Приведенные ниже фрагменты должны помочь читателю понять мои настройки кода:

Интерфейс IUnitOfWork

public interface IUnitOfWork<out TContext> where TContext : IDbContext

Класс UnitOfWork

public sealed class UnitOfWork<TContext> : IDisposable, IUnitOfWork<IDbContext> where TContext : IDbContext
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(UnitOfWork<TContext>));

        private readonly IDbContext _dbContext;
        private Dictionary<string, IRepository> _repositories;
        private IDbTransaction Transaction { get; set; }

        public UnitOfWork(IDbContext context)
        {
            _dbContext = context;
        }
    }

Регистрация контейнеров:

builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));

builder.RegisterType<ReconciliationDbContext>().As<IDbContext>();
builder.RegisterType<GenevaDataDbContext>().As<IDbContext>();
builder.RegisterType<OpenStaarsDbContext>().As<IDbContext>();

builder.RegisterType<UnitOfWork<ReconciliationDbContext>>().Keyed<IUnitOfWork<IDbContext>>(ContextKey.Recon);
builder.RegisterType<UnitOfWork<OpenStaarsDbContext>>().Keyed<IUnitOfWork<IDbContext>>(ContextKey.OpenStaars);

builder.RegisterType<CommentsService>().As<ICommentsService>().WithAttributeFiltering();

Классы DbContext:

public class ReconciliationDbContext : BaseDbContext<ReconciliationDbContext>, IDbContext
    {
        private const string DbSchema = "BoxedPosition";

        public ReconciliationDbContext() : base("Reconciliation")
        {

        }
    }

public class OpenStaarsDbContext : BaseDbContext<OpenStaarsDbContext>, IDbContext
    {
        public OpenStaarsDbContext() : base("OpenStaars")
        {

        }
    }

Комментарии Класс обслуживания:

public class CommentsService : ICommentsService
    {
        private readonly IUnitOfWork<IDbContext> _reconciliationUoW;

        public CommentsService([KeyFilter(ContextKey.Recon)] IUnitOfWork<IDbContext> reconciliationUoW)
        {
            _reconciliationUoW = reconciliationUoW;
        }
    }

Resolving ICommentsService:

var commentsService = container.Resolve<ICommentsService>();

Теперь, когда я пытаюсь разрешить тип ICommentsService, он создает зависимость UnitOfWork.Однако свойство UnitOfWork._dbContext соответствует типу OpenStaarsDbContext.Это особенно странно, учитывая наши регистрации.

enter image description here

Страннее становится, если мы переупорядочим наши регистрации IDbContext путем регистрации GenevaDataDbContext после OpenStaarsDbContext.Теперь _dbContext оценивается для экземпляра GenevaDataDbContext.

Как это исправить, чтобы зависимость CommentsService в файле recciliationUoW имела правильный экземпляр ReconciliationDbContext?

1 Ответ

0 голосов
/ 22 октября 2018

Причиной такого поведения является тот факт, что вы вводите IDbContext в конструктор UnitOfWork вместо TContext - контейнер просто игнорирует тип, который вы указали в качестве универсального параметра при регистрации, и принимает первое IDbContext он находит в контейнере - который будет последним зарегистрированным, независимо от того, какой ключ вы бы использовали.

Чтобы заставить его работать, вместо использования регистрации по ключу, вы могли бы просто ввести IUnitOfWork<ContextYouNeed> вместо IUnitOfWork<IDbContext> - это также упростило бы кодПрежде всего, вам нужно исправить свой UnitOfWork класс:

class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : IDbContext
{
    private readonly TContext _context;

    public UnitOfWork(TContext context)
    {
        _context = context;
    }
}

. При регистрации вам не нужно регистрировать определенные типы единиц работы, стандартной общей регистрации будет достаточно.Но вам также необходимо зарегистрировать типы контекста AsSelf, чтобы Autofac правильно внедрил его для экземпляров вашей единицы работы:

builder.RegisterGeneric(typeof(UnitOfWork<>)).As(typeof(IUnitOfWork<>));

builder.RegisterType<ReconciliationContext>().As<IContext>().AsSelf();
builder.RegisterType<OpenStaarsContext>().As<IContext>().AsSelf();

Позже в вашем сервисе просто введите правильную единицу работы:

public CommentsService(IUnitOfWork<ReconciliationContext> reconciliationUoW)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...