如何使用Simple Injector注册命名实例

时间:2014-12-19 08:20:07

标签: c# dependency-injection simple-injector

我正在开发一个WinForm应用程序,我正在使用Repository Pattern,我使用Servicestack OrmLite进行数据访问,使用Simple Injector进行IoC。

在我的program.cs中,我有2个注册2个不同的OrmLiteConnectionFactory,但目前我无法注册,因为我无法注册命名...使用FunQ我可以用

执行此操作
container.Register<IDbConnectionFactory>("db1", _ => new OrmLiteConnectionFactory(
    ConfigurationManager.ConnectionStrings["db1"].ConnectionString, 
    SqlServerDialect.Provider));
container.Register<IDbConnectionFactory>("db2", _ => new OrmLiteConnectionFactory(
    ConfigurationManager.ConnectionStrings["db2"].ConnectionString, 
    SqlServerDialect.Provider));

这是我的program.cs Bootstrap方法

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

提前致谢

1 个答案:

答案 0 :(得分:16)

由于您有两个不同的数据库,每个数据库都有不同的架构,因此不同的OrmLiteConnectionFactory不可互换。这意味着如果您更换它们,您的系统将停止工作。这表明你打破了Liskov Substitution Principle。因此,在这种情况下的一般解决方案是为每个工厂提供自己的接口,并让每个存储库依赖于该特定接口。这允许您唯一地注册它们,让容器毫无疑问地解析对象图。

如果给每个工厂自己的抽象不是一个选项,或者方便,另一个选择是注册您的存储库而不需要自动连接。通过向委托人注册您的存储库,您可以完全控制注入存储库的内容。例如:

container.Register<IOrderRepository>(() => new SqlOrderRepo(connectionFactory1));

container.Register<IUserRepository>(() => new SqlUserRepo(
    connectionFactory2,
    container.GetInstance<ILogger>()));

第三种选择是使用context based injection,如果您执行以下操作:

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

开箱即用Simple Injector不支持注册键控注册,但有几种方法可以按照此page的说明执行此操作。该页面还解释了为什么没有内置支持。这是一个深思熟虑的设计决定。