如何注册在ServiceStack.net使用Funq多个IDbConnectionFactory实例 [英] How to register multiple IDbConnectionFactory instances using Funq in ServiceStack.net

查看:321
本文介绍了如何注册在ServiceStack.net使用Funq多个IDbConnectionFactory实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你怎么会去登记在Funq diferent IDbConnectionFactory实例,那么你的服务中直接访问它们?不要命名实例以某种方式发挥作用吗?



这是跨业务使用不同的数据库时采取的最好的方法?



谢谢!



编辑:



这是例子)。我可以在这里下车的方式,因为我很新国际奥委会,但例如说我有2个,我想注入单独的数据库连接。在ServiceStack,这是在Global.asax完成

  container.Register< IDbConnectionFactory>(C => 
新OrmLiteConnectionFactory(@连接字符串1,SqlServerOrmLiteDialectProvider.Instance));

container.Register< IDbConnectionFactory>(C =>
新OrmLiteConnectionFactory(@连接字符串2,SqlServerOrmLiteDialectProvider.Instance));



这两个似乎被注入HONKY多莉。



这些都是然后自动在服务端通过这样的访问:

 公共IDbConnectionFactory DbFactory {搞定;组; } 

在这种情况下,这似乎是给我的第一个注册。我如何才能访问到服务端的特定的一个?希望这使得它多了几分清晰。



下面是从只使用1 IDbConnectionFactory ServiceStack.Examples一个羽翼丰满的例子:
电影休息


解决方案

上面我的问题仍然是有效的,但下面可能会帮助你啦。



Funq不支持自动构造函数注入(又名自动布线),你就必须手动通过构建这样做 Func键< T> lambda表达式。因为你已经在做手工构造函数注入,很容易选择什么 IDbConnectionFactory 你希望注入你的服务。例如:



<预类=郎-CS prettyprint-覆盖> IDbConnectionFactory yellowDbConFactory =
新YellowDbConnectionFactory();

IDbConnectionFactory blueDbConFactory =
新BlueDbConnectionFactory();

IDbConnectionFactory purpleDbConFactory =
新PurpleDbConnectionFactory();

container.Register< IService1>(C =>
新Service1Impl(yellowDbConFactory,
c.Resolve< IDep1>());

container.Register< IService2>(C =>
新Service2Impl(blueDbConFactory);

container.Register< IService3>(C =>
新Service3Impl(purpleDbConFactory,
c.Resolve< IDep2>());

当然你也可以使用一个名为注册的,像这样的:



<预类=郎-CS prettyprint-覆盖> container.Register< IDbConnectionFactory>(黄,
新YellowDbConnectionFactory());

container.Register< IDbConnectionFactory>(蓝色,
新BlueDbConnectionFactory());

container.Register< IDbConnectionFactory>( 紫,
新PurpleDbConnectionFactory());

container.Register< IService1>(C =>
新Service1Impl(
c.Resolve< IDbConnectionFactory> (黄色)
c.Resolve&所述; IDep1>());

container.Register< IService2>(C =>
新Service2Impl(
c.Resolve< IDbConnectionFactory>(蓝));

container.Register< IService3>(C =>
新Service3Impl(
c.Resolve< IDbConnectionFactory>(紫色),
c.Resolve< IDep2>());

由于缺乏对自动装配支持,你会与这些比较尴尬的登记结束,这将很快导致你的作文根维护的噩梦,不过这无关你的问题; - )



您通常应该尽量避免歧义您的注册。你的情况,你有一个单一的接口,做两件事情(连接到两个数据库)。除非这两个数据库共享相同的模型,每个数据库应该得到自己的接口(如果两个实现并不互换,你会违反里氏替换原则):



<预类=郎-CS prettyprint-覆盖> 接口IYellowDbConnectionFactory:IDbConnectionFactory
{
}

接口IPurpleDbConnectionFactory:IDbConnectionFactory
{
}

由于道路ServiceStack作品,你可能需要实现对每个实施



<预类=郎-CS prettyprint-覆盖> 类YellowDbConnectionFactory:OrmLiteConnectionFactory,
IYellowDbConnectionFactory
{
公YellowDbConnectionFactory(字符串s):基地(S){}
}

类PurpleDbConnectionFactory:OrmLiteConnectionFactory,
IPurpleDbConnectionFactory
{
公共YellowDbConnectionFactory(字符串s) :基地(S){}
}

现在你应该改变你的服务的定义使用而不是使用 IDbConnectionFactory 具体的接口:



<预类=郎-CS prettyprint-覆盖> 公共类MovieService:RestServiceBase<电影及GT;
{
私人只读IYellowDbConnectionFactory dbFactory;

公共MovieService(IYellowDbConnectionFactory工厂)
{
this.dbFactory =厂;
}
}

请注意,这个类现在使用构造函数注入,而不是财产注射。你可以得到这个财产注入工作,但它通常是更好地去构造器注入。这里是一个 SO质疑一下吧。



通过Funq,配置将那么是这样的:



<预类=郎-CS prettyprint-覆盖> container.Register< MovieService>(C =>
新MovieService(
c.Resolve< IYellowDbConnectionFactory>());

这两个新的接口和两个类,并更改为 MovieService 没赢你很多,因为Funq不支持自动布线。你将成为一个谁是手动一起布线的一切。但是,当你切换到一个框架,它的确实的支持自动布线,这样的设计使容器注入合适的依赖关系,而不一个问题,因为没有什么注入讨论


How would you go about registering diferent IDbConnectionFactory instances in Funq and then access them directly within your services? Do named instances somehow come into play here?

Is this the best approach to take when using different databases across services?

Thanks!

EDIT:

An example ;). I could be way off here because I'm pretty new to IoC, but say for example I have 2 separate database connections that I'd like to inject. In ServiceStack, this is done in the Global.asax.

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

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

Both of these seem to be injected honky dory.

These are then accessed automatically on the service end via something like this:

public IDbConnectionFactory DbFactory { get; set; }

In this case, it seems to be giving me the first one registered. How can I get access to a specific one on the service end? Hopefully that makes it a little more clear.

Here's a full fledged example from ServiceStack.Examples that only uses 1 IDbConnectionFactory: Movies Rest

解决方案

My question above is still valid, but the following might help you anyway.

Funq does not support automatic constructor injection (a.k.a. auto wiring), and you will have to do this by hand by constructing Func<T> lambda expressions. Because you are already doing constructor injection by hand, it is easy to choose what IDbConnectionFactory you wish to inject into your services. Example:

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>());

Of course you can also used named registrations, like this:

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>());

Because of the lack of support for auto-wiring, you'll end up with these rather awkward registrations, and this will pretty soon result in a maintenance nightmare of your composition root, but that's unrelated to your question ;-)

You should usually try to prevent ambiguity in your registration. In your case you've got a single interface, that does two things (connects to two databases). Unless both database share the exact same model, each database deserves its own interface (if the two implementations are not interchangable, you'll be violating the Liskov substitution principle):

interface IYellowDbConnectionFactory : IDbConnectionFactory
{
}

interface IPurpleDbConnectionFactory : IDbConnectionFactory
{
}

Because of the way ServiceStack works, you probably need to implement an implementation for each:

class YellowDbConnectionFactory : OrmLiteConnectionFactory,
    IYellowDbConnectionFactory
{
    public YellowDbConnectionFactory(string s) : base(s){}
}

class PurpleDbConnectionFactory : OrmLiteConnectionFactory,
    IPurpleDbConnectionFactory 
{
    public YellowDbConnectionFactory(string s) : base(s){}
}

Now you should change the definition of your services to use the specific interface instead of using the IDbConnectionFactory:

public class MovieService : RestServiceBase<Movie>
{
    private readonly IYellowDbConnectionFactory dbFactory;

    public MovieService(IYellowDbConnectionFactory factory)
    {
        this.dbFactory = factory;
    }
}

Note that this class now uses constructor injection instead of property injection. You can get this to work with property injection, but it is usually better to go with constructor injection. Here is a SO question about it.

With Funq, your configuration will then look like this:

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

Those two new interfaces and two classes and change to the MovieService didn't win you a lot, because Funq doesn't support auto-wiring. You will be the one who is wiring everything together manually. However, when you switch to a framework that does support auto-wiring, this design allows the container to inject the right dependencies without a problem, because there is no discussion about what to inject.

这篇关于如何注册在ServiceStack.net使用Funq多个IDbConnectionFactory实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆