Jef*_*ell 18 c# ioc-container inversion-of-control servicestack funq
您将如何在Funq中注册不同的IDbConnectionFactory实例,然后直接在您的服务中访问它们?命名实例会以某种方式在这里发挥作用吗?
这是跨服务使用不同数据库时最好的方法吗?
谢谢!
编辑:
一个例子 ;).我可能会离开这里,因为我对IoC很新,但是比如说我有2个独立的数据库连接,我想注入.在ServiceStack中,这是在Global.asax中完成的.
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(@"Connection String 1", SqlServerOrmLiteDialectProvider.Instance));
container.Register<IDbConnectionFactory>(c =>
new OrmLiteConnectionFactory(@"Connection String 2", SqlServerOrmLiteDialectProvider.Instance));
Run Code Online (Sandbox Code Playgroud)
这两个似乎都注入了谦逊的海鲂.
然后通过以下方式在服务端自动访问它们:
public IDbConnectionFactory DbFactory { get; set; }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它似乎给了我第一个注册.如何访问服务端的特定访问权限?希望这会让它更加清晰.
这是ServiceStack.Examples的完整示例,仅使用1个IDbConnectionFactory: Movies Rest
Ste*_*ven 14
我上面的问题仍然有效,但无论如何,以下内容可能会对您有所帮助.
Funq不支持自动构造函数注入(也称为自动布线),您必须通过构造Func<T>lambda表达式手动完成此操作.因为您已经手动进行构造函数注入,所以很容易选择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>());
Run Code Online (Sandbox Code Playgroud)
当然你也可以使用命名注册,如下所示:
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>());
Run Code Online (Sandbox Code Playgroud)
由于缺乏对自动布线的支持,你最终会得到这些相当尴尬的注册,这很快就会导致你的组合根的维护噩梦,但这与你的问题无关;-)
您通常应该尽量避免注册时出现歧义.在你的情况下,你有一个单独的接口,它做两件事(连接到两个数据库).除非两个数据库共享完全相同的模型,否则每个数据库都应该拥有自己的接口(如果这两个实现不可互换,则会违反Liskov替换原则):
interface IYellowDbConnectionFactory : IDbConnectionFactory
{
}
interface IPurpleDbConnectionFactory : IDbConnectionFactory
{
}
Run Code Online (Sandbox Code Playgroud)
由于ServiceStack的工作方式,您可能需要为每个实现一个实现:
class YellowDbConnectionFactory : OrmLiteConnectionFactory,
IYellowDbConnectionFactory
{
public YellowDbConnectionFactory(string s) : base(s){}
}
class PurpleDbConnectionFactory : OrmLiteConnectionFactory,
IPurpleDbConnectionFactory
{
public YellowDbConnectionFactory(string s) : base(s){}
}
Run Code Online (Sandbox Code Playgroud)
现在,您应该更改服务的定义以使用特定的界面,而不是使用IDbConnectionFactory:
public class MovieService : RestServiceBase<Movie>
{
private readonly IYellowDbConnectionFactory dbFactory;
public MovieService(IYellowDbConnectionFactory factory)
{
this.dbFactory = factory;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,此类现在使用构造函数注入而不是属性注入.您可以使用属性注入来实现此功能,但通常最好使用构造函数注入.这是一个关于它的SO问题.
使用Funq,您的配置将如下所示:
container.Register<MovieService>(c =>
new MovieService(
c.Resolve<IYellowDbConnectionFactory>());
Run Code Online (Sandbox Code Playgroud)
这两个新的接口和两个类并改变了MovieService并没有赢得你很多,因为Funq不支持自动布线.你将成为手动连接所有东西的人.然而,当你切换到一个框架,它不支持自动布线,这样的设计允许容器没有问题注入合适的依赖关系,因为没有什么注入讨论.
myt*_*thz 11
虽然Funq不支持自动布线,但它的ServiceStack实现确实如此.最新版本的ServiceStack包含Funq.Container重载:
container.RegisterAutoWired<T>();
container.RegisterAutoWiredAs<T,TAs>();
container.RegisterAs<T,TAs>();
Run Code Online (Sandbox Code Playgroud)
所以在Steven的例子中你也可以这样做:
container.RegisterAs<YellowDbConnectionFactory,IYellowDbConnectionFactory>();
Run Code Online (Sandbox Code Playgroud)
它会自动为您注册依赖项.