如何在ServiceStack.net中使用Funq注册多个IDbConnectionFactory实例

您将如何在Funq中注册不同的IDbConnectionFactory实例,然后直接在您的服务中访问它们? 命名实例在某种程度上发挥作用?

这是跨服务使用不同数据库时最好的方法吗?

谢谢!

编辑:

一个例子 ;)。 我可能会离开这里因为我对IoC很新,但是比如说我有2个独立的数据库连接,我想注入。 在ServiceStack中,这是在Global.asax中完成的。

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

这两个似乎都注入了骄傲的海鲂。

然后通过以下方式在服务端自动访问它们:

 public IDbConnectionFactory DbFactory { get; set; } 

在这种情况下,它似乎给了我第一个注册的。 如何在服务端访问特定的访问权限? 希望这会让它更加清晰。

这是ServiceStack.Examples中一个完整的示例,仅使用1个IDbConnectionFactory: Movies Rest

我上面的问题仍然有效,但无论如何,以下内容可能会对您有所帮助。

Funq不支持自动构造函数注入(也称为自动布线),您必须通过构造Func lambda表达式来手动执行此操作。 因为您已经手动执行构造函数注入,所以很容易选择要注入服务的IDbConnectionFactory 。 例:

 IDbConnectionFactory yellowDbConFactory = new YellowDbConnectionFactory(); IDbConnectionFactory blueDbConFactory = new BlueDbConnectionFactory(); IDbConnectionFactory purpleDbConFactory = new PurpleDbConnectionFactory(); container.Register(c => new Service1Impl(yellowDbConFactory, c.Resolve()); container.Register(c => new Service2Impl(blueDbConFactory); container.Register(c => new Service3Impl(purpleDbConFactory, c.Resolve()); 

当然你也可以使用命名注册,如下所示:

 container.Register("yellow", new YellowDbConnectionFactory()); container.Register("blue", new BlueDbConnectionFactory()); container.Register("purple", new PurpleDbConnectionFactory()); container.Register(c => new Service1Impl( c.Resolve("yellow"), c.Resolve()); container.Register(c => new Service2Impl( c.Resolve("blue")); container.Register(c => new Service3Impl( c.Resolve("purple"), c.Resolve()); 

由于缺乏对自动布线的支持,你最终会得到这些相当尴尬的注册,这很快就会导致你的组合根的维护噩梦,但这与你的问题无关;-)

您通常应该尽量避免注册时出现歧义。 在你的情况下,你有一个单独的接口,它做两件事(连接到两个数据库)。 除非两个数据库共享完全相同的模型,否则每个数据库都应该拥有自己的接口(如果这两个实现不可互换,则会违反Liskov替换原则 ):

 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 { private readonly IYellowDbConnectionFactory dbFactory; public MovieService(IYellowDbConnectionFactory factory) { this.dbFactory = factory; } } 

请注意,此类现在使用构造函数注入而不是属性注入。 您可以使用属性注入来实现此function,但通常最好使用构造函数注入。 这是一个关于它的SO问题 。

使用Funq,您的配置将如下所示:

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

这两个新的接口和两个类以及对MovieService改变并没有赢得很多,因为Funq不支持自动布线。 您将成为手动连接所有东西的人。 但是,当您切换到支持自动连接的框架时,此设计允许容器注入正确的依赖项而不会出现问题,因为没有关于要注入的内容的讨论。

虽然Funq不支持自动布线,但ServiceStack实现了它。 最新版本的ServiceStack包含Funq.Container重载:

 container.RegisterAutoWired(); container.RegisterAutoWiredAs(); container.RegisterAs(); 

所以在史蒂文的例子中你也可以这样做:

 container.RegisterAs(); 

它会自动为您注册依赖项。

我以为我会在这里筹码2美分,但我意识到这个问题很老了。 我想从ServiceStack访问事务数据库和日志数据库,这就是我最终从AppHostBase Configure()方法执行的操作:

  container.Register( 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; }); 

默认情况下,从工厂打开连接时使用“MyTransactionDB”,但我可以通过以下方式从服务显式访问日志数据库:

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

尝试使用Repository模式而不是这个IoC(这会使事情不必要地复杂化)。 上面的代码似乎不起作用。 怀疑事情发生了变化。 我还不清楚注册IDbConnectionFactory如何神奇地填充IDbConnection属性。 会喜欢这个解释。 如果有人使用ServiceStack IoC容器确实可以使用它,那么我很想知道如何使用它。 更新SS文档会非常有益(我很乐意这样做)