Внедрение в конструктор Unity не разрешает хранилища, как ожидалось - PullRequest
1 голос
/ 04 декабря 2011

Я использую Unity для разрешения Реализации универсальных репозиториев Майка Хэдлоу (linq to sql flavour) для нескольких баз данных. Конфигурация контейнера, которая работает:

container.RegisterType<IConnectionStringProvider, HistoryConnectionProvider>(new TransientLifetimeManager())
         .RegisterType<IConnectionStringProvider, MetaConnectionProvider>("meta", new TransientLifetimeManager())
         .RegisterType<IDataContextProvider, DataContextProvider>(new TransientLifetimeManager())
         .RegisterType<IDataContextProvider, DataContextProvider>("meta", new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IConnectionStringProvider>("meta")))
         // this registration of Repository<> resolves the history database by default
         .RegisterType(typeof(IRepository<>), typeof(Repository<>), new TransientLifetimeManager());
         // anything not targeting this database has to be declared
         .RegisterType<IRepository<SpecificType>, Repository<SpecificType>>(new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<DataContextProvider>("meta")));

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

IConnectionStringProvider historyConnectionProvider = new ConnectionProvider(connections.HistoryConnectionString);
IConnectionStringProvider metaConnectionProvider = new ConnectionProvider(connections.MetaConnectionString);

container.RegisterType<IDataContextProvider, DataContextProvider>("history", new TransientLifetimeManager(), new InjectionConstructor(historyConnectionProvider))
         .RegisterType<IDataContextProvider, DataContextProvider>("meta", new TransientLifetimeManager(), new InjectionConstructor(metaConnectionProvider))
         .RegisterType(typeof(IHistoryRepository<>), typeof(Repository<>), new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDataContextProvider>("history")))
         .RegisterType(typeof(IMetaRepository<>), typeof(Repository<>), new TransientLifetimeManager(), new InjectionConstructor(new ResolvedParameter<IDataContextProvider>("meta")));

К сожалению, это не работает. Результатом является последний зарегистрированный тип IDataContextProvider, внедряемый в каждый тип репозитория. Заранее спасибо за любую помощь.

Ответы [ 2 ]

0 голосов
/ 17 декабря 2011

Решение исходного вопроса

Для Unity необходим уникальный тип, а также интерфейс.Я все еще не уверен, почему инжектор конструктора не справился с этим.Это работает:

// where IMetaRepository<T> and MetaRepository<T> both are derived place holders
container.RegisterType(typeof(IMetaRepository<>), typeof(MetaRepository<>), new TransientLifetimeManager());

К сожалению, это создает ситуацию, когда потребляющие классы должны знать, откуда поступают их данные, что меня не устраивало.

ЛучшеДизайн

Я хотел оставить свои dbmls сгенерированными (так что это исключило возможность привязки моих моделей к определенному интерфейсу), поэтому я просто бросил их в разные подпапки, в результате чего дизайнер сгенерировал другое пространство имендля каждой базы данных.

Затем, в своей реализации репозитория, я сделал следующее:

public Repository(IConnections connections)
{
  T type = new T();
  var ns = type.GetType().Namespace;
  if (ns == "Project.Common.DAL.History")
  {
    _dataContext = new DataContext(connections.HistoryConnectionString);
  }
  else if (ns == "Project.Common.DAL.Transaction")
  {
    _dataContext = new DataContext(connections.TransactionConnectionString);
  }
  else
  {
    _dataContext = new DataContext(connections.MetaConnectionString);
  }
}

Я думаю, что одним из шагов после этого было бы создание собственного распознавателя типов для единицы, чтобы проверитьпространство имен для меня и вернемся к внедрению контекста данных (это будет необходимо до того, как единица работы может быть реализована).Я пока не собираюсь отмечать это как ответ, если у кого-то есть лучшее решение.

0 голосов
/ 05 декабря 2011

Даниэль, на втором наборе кода, какова цель именования отдельных регистраций? Вы уже решили иметь отдельные интерфейсы для каждой базы данных, поэтому, кажется, нет необходимости иметь имя для нее. Я мог бы быть недоразумением, хотя. Более того, во втором примере, если Respository может выполнять интерфейс для IMeta и IHistory, тогда возникает вопрос, в чем разница между ними.

Если бы я дал вам пример кода, как добиться того, чего вы хотите, он бы выглядел очень похоже на ваш первый пример, который на самом деле не намного более многословен, чем последний.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...