Как зарегистрировать несколько экземпляров IDbConnectionFactory с помощью Funq в ServiceStack.net

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

является ли это лучшим подходом при использовании разных баз данных в разных службах?

спасибо!

EDIT:

пример ;). Я мог бы быть здесь, потому что я довольно новичок в IoC, но, например, у меня есть 2 отдельные базы данных связи, которые я хотел бы ввести. В ServiceStack это делается в глобальном масштабе.асакс.

container.Register<IDbConnectionFactory>(c =>
            new OrmLiteConnectionFactory(@"Connection String 1", SqlServerOrmLiteDialectProvider.Instance));                                             

container.Register<IDbConnectionFactory>(c =>
            new OrmLiteConnectionFactory(@"Connection String 2", SqlServerOrmLiteDialectProvider.Instance));                

оба они, кажется, впрыснуты honky dory.

они затем автоматически доступны на конце службы через что-то вроде этого:

public IDbConnectionFactory DbFactory { get; set; }

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

вот полноценный пример из ServiceStack.Примеры, использующие только 1 IDbConnectionFactory: Фильмы Остальные

4 ответов


мой вопрос выше по-прежнему действителен, но следующее может помочь вам в любом случае.

Funq не поддерживает автоматическую инъекцию конструктора (a.к. 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;
    }
}

обратите внимание, что этот класс теперь использует инъекция конструктора вместо инъекции свойства. Вы можете заставить это работать с инъекцией свойств, но обычно лучше идти с инъекцией конструктора. Вот это поэтому вопрос об этом.

С помощью Funq ваша конфигурация будет выглядеть следующим образом:

container.Register<MovieService>(c =>
    new MovieService(
        c.Resolve<IYellowDbConnectionFactory>());

эти два новых интерфейса и два класса и изменить на MovieService не выиграл вас много, потому что Funq не поддерживает автоматическую проводку. Ты будешь тем, кто все подключает. вместе вручную. Однако, когда вы переключаетесь на фреймворк, который тут поддержите автоматическ-проводку, эта конструкция позволяет контейнеру впрыснуть правые зависимости без проблемы, потому что никакое обсуждение о что впрыснуть.


хотя Funq не поддерживает автоматическую проводку,ServiceStack реализация этого делает. Последняя версия ServiceStack включает в себя Funq.Перегрузки контейнера:

container.RegisterAutoWired<T>();
container.RegisterAutoWiredAs<T,TAs>();
container.RegisterAs<T,TAs>();

Так, в Примере Стивена вы также можете сделать:

container.RegisterAs<YellowDbConnectionFactory,IYellowDbConnectionFactory>();

и он автоматически зарегистрирует зависимостей.


думал, что я бы скинул свои 2 цента здесь, хотя я понимаю, что вопрос довольно старый. Я хотел получить доступ к транзакционной БД и БД ведения журнала из ServiceStack, и вот как я закончил это делать из метода Apphostbase Configure ():

            container.Register<IDbConnectionFactory>(
                c => {
                    OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["MyTransactionalDB"].ConnectionString, MySqlDialect.Provider);
                    dbFactory.ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current);
                    dbFactory.RegisterConnection("LoggingDB", ConfigurationManager.ConnectionStrings["MyLoggingDB"].ConnectionString, MySqlDialect.Provider);

                    return dbFactory;
                });

по умолчанию "MyTransactionalDB" используется при открытии соединения с завода, но я могу явно получить доступ к БД ведения журнала из службы через:

        using (var db = DbFactory.Open("LoggingDB"))
        {
            db.Save(...);
        }

попробуйте использовать шаблон репозитория вместо этого IoC (что просто усложняет вещи без необходимости). Приведенный выше код не работает. Подозреваю, что-то изменилось. Я все еще не понимаю, как регистрация IDbConnectionFactory волшебным образом заполняет свойство IDbConnection. Хотелось бы получить какое-то объяснение. Если кто-то когда-либо получит эту работу, используя контейнер ServiceStack IoC.. тогда я хотел бы посмотреть, как. И было бы очень полезно обновить документы SS (я вполне счастлив сделать это)