I'm developing a WinForm application and I'm using Repository Pattern , I'm using Servicestack OrmLite for data access and Simple Injector for IoC.
In my program.cs I have 2 register 2 different OrmLiteConnectionFactory
but currently I'm not able to since I can't register named... with FunQ I can do this with
container.Register<IDbConnectionFactory>("db1", _ => new OrmLiteConnectionFactory(
ConfigurationManager.ConnectionStrings["db1"].ConnectionString,
SqlServerDialect.Provider));
container.Register<IDbConnectionFactory>("db2", _ => new OrmLiteConnectionFactory(
ConfigurationManager.ConnectionStrings["db2"].ConnectionString,
SqlServerDialect.Provider));
here is mine program.cs Bootstrap method
private static void Bootstrap()
{
// Create the container as usual.
Container = new Container();
string conn1 = ConfigurationManager.ConnectionStrings["dbconn1"].ConnectionString;
string conn2 = ConfigurationManager.ConnectionStrings["dbconn2"].ConnectionString;
OrmLiteConnectionFactory connectionFactory = new OrmLiteConnectionFactory(conn1,
ServiceStack.OrmLite.SqlServer.SqlServerOrmLiteDialectProvider.Instance);
Container.RegisterSingle<OrmLiteConnectionFactory>(connectionFactory1);
OrmLiteConnectionFactory connectionFactory2 = new OrmLiteConnectionFactory(conn2,
ServiceStack.OrmLite.SqlServer.SqlServerOrmLiteDialectProvider.Instance);
// how do I register this one without a name?
Container.RegisterSingle<OrmLiteConnectionFactory>(connectionFactory2);
Container.Register<MainForm>();
}
Thanks in advance
Since you have have two different databases with each a different schema, the different OrmLiteConnectionFactory
aren't interchangable. This means that if you swap them around, your system will stop working. That's an indication that you are breaking the Liskov Substitution Principle. So the general solution in that case is to give each factory its own interface and let each repository depend on that particular interface. That allows you to register them uniquely and let the container resolve the object graph without doubt.
If giving each factory its own abstraction is not an option, or convenient, another option is to register your repositories without auto-wiring. By registering your repository with a delegate, you are completely in control over what to inject into your repository. For instance:
container.Register<IOrderRepository>(() => new SqlOrderRepo(connectionFactory1));
container.Register<IUserRepository>(() => new SqlUserRepo(
connectionFactory2,
container.GetInstance<ILogger>()));
A third option is to use context based injection, were you do the following:
var f1 = Lifestyle.Singleton.CreateRegistration<IDbConnectionFactory>(
() => new OrmLiteConnectionFactory(
conn1,
ServiceStack.OrmLite.SqlServer.SqlServerOrmLiteDialectProvider.Instance),
container);
var f2 = Lifestyle.Singleton.CreateRegistration<IDbConnectionFactory>(
() => new OrmLiteConnectionFactory(
conn2,
ServiceStack.OrmLite.SqlServer.SqlServerOrmLiteDialectProvider.Instance),
container);
container.RegisterConditional(typeof(IDbConnectionFactory), f1, InjectedInto<SqlOrderRepo>);
container.RegisterConditional(typeof(IDbConnectionFactory), f2, InjectedInto<SqlUserRepo>);
// Helper method.
static bool InjectedInto<T>(PredicateContext c) =>
c.Consumer.ImplementationType == typeof(T);
Out of the box Simple Injector does not support registering keyed registrations, but there are several ways to do this as explained on this page. That page also explains why there is no built-in support for this. This is a deliberate design decision.