我正在使用现有的WebApi,它使用SimpleInjector注册单个数据库连接。我需要建立一个端点来从不同的数据库获取信息,但我不知道如何注册新的连接。
这些是主db的现有注册:
_container.Register<IDataBaseSqlServerDapper>(
() => new DataBaseSqlServerDapper(SqlServerDb.ConnectionString(),
LogManager.GetLogger("")));
_container.RegisterWebApiRequest<IDbConnectionFactory>(
() => new OrmLiteConnectionFactory(SqlServerDb.ConnectionString(),
new SqlServerOrmLiteDialectProvider()));
_container.RegisterWebApiRequest(
() => new PetaPoco.Database(Connection.SurveyEngine) {
IsolationLevel = IsolationLevel.Snapshot
});
所以我读了一下RegisterCollection方法,我尝试了以下内容:
_container.RegisterCollection<IDataBaseSqlServerDapper>(new[]
{
new DataBaseSqlServerDapper(SqlServerDb.ConnectionString(), LogManager.GetLogger("")),
new DataBaseSqlServerDapper(AdmbbDb.ConnectionString(), LogManager.GetLogger(""))
});
_container.RegisterCollection<IDbConnectionFactory>(new[]
{
new OrmLiteConnectionFactory(
SqlServerDb.ConnectionString(),
new SqlServerOrmLiteDialectProvider()),
new OrmLiteConnectionFactory(
AdmbbDb.ConnectionString(),
new SqlServerOrmLiteDialectProvider())
});
_container.RegisterCollection<PetaPoco.Database>(new[]
{
new PetaPoco.Database(Connection.SurveyEngine) {
IsolationLevel = IsolationLevel.Snapshot },
new PetaPoco.Database(Connection.Admbb) {
IsolationLevel = IsolationLevel.Snapshot }
});
SqlServerDb,AdmbbDd和Connection是包含连接字符串名称的类。
但是我收到了这个错误:
配置无效。为类型IDapperQueryFactory创建实例失败。 DapperQueryFactory类型的构造函数包含名称为&#39; dataBaseSqlServerDapper&#39;的参数。并键入未注册的IDataBaseSqlServerDapper。请确保已注册IDataBaseSqlServerDapper,或更改DapperQueryFactory的构造函数。但是,IEnumerable&lt; IDataBaseSqlServerDapper&gt;的注册;你的意思是依赖于IEnumerable&lt; IDataBaseSqlServerDapper&gt;?
我该如何解决这个问题?
答案 0 :(得分:2)
在现有情况下,您指定可以使用类型IDataBaseSqlServerDapper
进行注入,然后将其正确注入对象(在本例中为实现IDapperQueryFactory
的类)。
在第二种情况下,您正在注册类型为IDataBaseSqlServerDapper
的服务。这意味着您的DI不知道如何解析单个IDataBaseSqlServerDapper
,只知道它们的集合。
这意味着您必须更改构造函数以接受IEnumerable<IDataBaseSqlServerDapper>
或注册非集合IDataBaseSqlServerDapper
他们的文档列出了一个很好的例子,说明如何同时使用Register和RegisterCollection使其工作(source)。
至于你的问题,你说:
我需要建立一个端点来从不同的数据库获取信息,但我不知道如何注册新连接。
如果您只是想改变数据的去向,那么您是否只能替换旧的现有处理程序?
如果您的目标是从多个数据源加载数据,那么您需要具有某种逻辑,允许您的代码确定应该使用哪个源来存储/加载数据。
simpleinjector文档中的示例为此类提供了良好的基础,不需要您重写使用注入IDataBaseSqlServerDapper
的类。
答案 1 :(得分:0)
我的情况与此类似,但简单一些。我正在为遇到类似我的问题的任何人发布我的解决方案。
我需要一种方法来使用以不同参数(连接字符串名称)初始化的单个具体类型(在我的情况下为NPoco.Database
)的多个实例。由于SimpleInjector doc examples使用实现ILogger
和的类都具有无参数的构造函数,因此我发现很难弄清楚如何使我的方案工作。
我终于想出了一个简单的NPoco.Database
子类,它需要连接到每个数据库,然后使用Container.RegisterConditional
注册实例。由于RegisterConditional
没有带构造函数的重载,因此我必须给这些子类中的每个无参数构造函数,这些构造函数使用适当的连接字符串名称调用了基础Database
类。最后,一些使用者来自外部NuGet程序包(在我的组织内部),并且依赖于注入IDatabase
而不是派生类型,因此我不能仅仅依靠注册派生类型并让SimpleInjector根据仅此而已。
话虽如此,这是我的解决方法。
public class FirstSubDatabase : Database
{
public FirstSubDatabase()
: base("FirstSubConnection") { }
}
public class SecondSubDatabase : Database
{
public SecondSubDatabase()
: base("SecondSubConnection") { }
}
container.RegisterConditional<IDatabase, FirstSubDatabase>(
Lifestyle.Scoped,
c => c.Consumer.ImplementationType.FullName?.StartsWith(
"external.lib.", StringComparison.OrdinalIgnoreCase) ?? false);
container.RegisterConditional<IDatabase, SecondSubDatabase>(
Lifestyle.Scoped,
c => c.Consumer.ImplementationType == typeof(LocalConsumerClass));
注意:“ external.lib”。只是外部NuGet包中所有内容的名称空间。这样可以避免将来的编辑者(包括我自己)不得不花时间弄清楚为什么要实例化对该包中的另一个服务的依赖。