Ответ 1
Мой вопрос выше по-прежнему действителен, но в любом случае вам может помочь следующее.
Funq не поддерживает автоматическую вставку конструктора (автоматическая проводка a.k.a.), и вам придется сделать это вручную, построив выражения Func<T>
лямбда. Поскольку вы уже делаете инъекцию конструктора вручную, легко выбрать, что IDbConnectionFactory
вы хотите ввести в свои службы. Пример:
IDbConnectionFactory yellowDbConFactory =
new YellowDbConnectionFactory();
IDbConnectionFactory blueDbConFactory =
new BlueDbConnectionFactory();
IDbConnectionFactory purpleDbConFactory =
new PurpleDbConnectionFactory();
container.Register<IService1>(c =>
new Service1Impl(yellowDbConFactory,
c.Resolve<IDep1>());
container.Register<IService2>(c =>
new Service2Impl(blueDbConFactory);
container.Register<IService3>(c =>
new Service3Impl(purpleDbConFactory,
c.Resolve<IDep2>());
Конечно, вы также можете использовать именованные регистрации, например:
container.Register<IDbConnectionFactory>("yellow",
new YellowDbConnectionFactory());
container.Register<IDbConnectionFactory>("blue",
new BlueDbConnectionFactory());
container.Register<IDbConnectionFactory>("purple",
new PurpleDbConnectionFactory());
container.Register<IService1>(c =>
new Service1Impl(
c.Resolve<IDbConnectionFactory>("yellow"),
c.Resolve<IDep1>());
container.Register<IService2>(c =>
new Service2Impl(
c.Resolve<IDbConnectionFactory>("blue"));
container.Register<IService3>(c =>
new Service3Impl(
c.Resolve<IDbConnectionFactory>("purple"),
c.Resolve<IDep2>());
Из-за отсутствия поддержки для автоматической проводки вы закончите с этими довольно неудобными регистрациями, и это довольно скоро приведет к кошмару обслуживания вашего корня композиции, но не связанному с вашим вопросом; -)
Обычно вы должны стараться предотвратить неоднозначность при регистрации. В вашем случае у вас есть один интерфейс, который выполняет две функции (подключается к двум базам данных). Если обе базы данных не разделяют одну и ту же модель, каждая база данных заслуживает собственного интерфейса (если две реализации не взаимозаменяемы, вы будете нарушать Принцип замены Лискова):
interface IYellowDbConnectionFactory : IDbConnectionFactory
{
}
interface IPurpleDbConnectionFactory : IDbConnectionFactory
{
}
Из-за того, как работает ServiceStack, вам, вероятно, необходимо реализовать реализацию для каждого:
class YellowDbConnectionFactory : OrmLiteConnectionFactory,
IYellowDbConnectionFactory
{
public YellowDbConnectionFactory(string s) : base(s){}
}
class PurpleDbConnectionFactory : OrmLiteConnectionFactory,
IPurpleDbConnectionFactory
{
public YellowDbConnectionFactory(string s) : base(s){}
}
Теперь вы должны изменить определение своих сервисов для использования конкретного интерфейса вместо использования IDbConnectionFactory
:
public class MovieService : RestServiceBase<Movie>
{
private readonly IYellowDbConnectionFactory dbFactory;
public MovieService(IYellowDbConnectionFactory factory)
{
this.dbFactory = factory;
}
}
Обратите внимание, что этот класс теперь использует инъекцию конструктора вместо инъекции свойства. Вы можете заставить это работать с инъекцией свойств, но обычно лучше идти с инжектором конструктора. Вот SO вопрос об этом.
С помощью Funq ваша конфигурация будет выглядеть следующим образом:
container.Register<MovieService>(c =>
new MovieService(
c.Resolve<IYellowDbConnectionFactory>());
Эти два новых интерфейса и два класса и переход на MovieService
не выиграли вас много, потому что Funq не поддерживает автоматическую проводку. Вы будете тем, кто проводит все вместе вручную. Однако, когда вы переключаетесь на фреймворк, который поддерживает автоматическую проводку, этот проект позволяет контейнеру вводить правильные зависимости без проблем, потому что нет обсуждения того, что нужно вводить.