C# 如何使用特定于数据库的存储库

C# 如何使用特定于数据库的存储库,c#,simple-injector,C#,Simple Injector,我将SimpleInjector用于我的WinC窗体应用程序。 我需要在运行时决定访问Oracle或SqlServer的存储库,因为这取决于用户希望连接到哪个数据库。 目前我是这样做的,当我为存储库添加一个装饰器时,它就失败了 _container.RegisterCollection<IRepository>( new[] { typeof(OraRepository), typeof(SqlRepository) }); 运行测试: [TestMethod()] pub

我将SimpleInjector用于我的WinC窗体应用程序。 我需要在运行时决定访问Oracle或SqlServer的存储库,因为这取决于用户希望连接到哪个数据库。 目前我是这样做的,当我为存储库添加一个装饰器时,它就失败了

_container.RegisterCollection<IRepository>(
    new[] { typeof(OraRepository), typeof(SqlRepository) });
运行测试:

[TestMethod()]
public void GetRepoTest()
{
    var repo = _provider.GetRepo<ICarRepository>(true);
    Assert.AreEqual(typeof(OraCarRepository), repo.GetType());

    repo = _provider.GetRepo<ICarRepository>(false);
    Assert.AreEqual(typeof(SqlCarRepository), repo.GetType());

    var repo2 = _provider.GetRepo<ITruckRepository>(true);
    Assert.AreEqual(typeof(OraTruckRepository), repo2.GetType());

    repo2 = _provider.GetRepo<ITruckRepository>(false);
    Assert.AreEqual(typeof(SqlTruckRepository), repo2.GetType());
}

你的问题其实不容易回答

我的胃告诉我,依赖上面显示的类型的字符串名是不对的。如何正确地做到这一点

根据您当前的设计,我可以想象将您的RepoProvider实现更改为以下内容:

private Dictionary<Type, InstanceProducer> oracle;
private Dictionary<Type, InstanceProducer> sql;

public RepoProvider(
    Dictionary<Type, InstanceProducer> oracle, 
    Dictionary<Type, InstanceProducer> sql)
{
    this.oracle = oracle;
    this.sql = sql;
}

public T GetRepo<T>(bool oracle)  where T : class
{
    Dictionary<Type, InstanceProducer> repos = oracle ? this.oracle : this.sql;
    return (T)repos[typeof(T)].GetInstance();
}
您可以按如下方式注册:

container.RegisterSingleton<IRepoProvider>(new RepoProvider(
    oracle: new Dictionary<Type, InstanceProducer>
    {
        { typeof(ICarRepository), Lifestyle.Transient.CreateProducer<ICarRepository, OraCarRepository>(container) },
        { typeof(ITruckRepository), Lifestyle.Transient.CreateProducer<ITruckRepository, OraTruckRepository>(container) },
    },
    sql: new Dictionary<Type, InstanceProducer>
    {
        { typeof(ICarRepository), Lifestyle.Transient.CreateProducer<ICarRepository, SqlCarRepository>(container) },
        { typeof(ITruckRepository), Lifestyle.Transient.CreateProducer<ITruckRepository, SqlTruckRepository>(container) },
    });

这允许您在不破坏系统的情况下应用装饰程序。

如何选择存储库?用户是否在应用程序运行时从一个数据库更改为另一个数据库,或者在启动时(例如,通过在配置文件中指定)确定一次?是的,在应用程序运行时确定。用户可以选择在Oracle上运行一个分析,在SqlServer上运行下一个分析,而无需重新启动应用程序。此外,处理的数据格式相同。oracle或sqlserver数据由相应的存储库放入业务实体,以便在业务层进行进一步处理@史蒂文:有没有关于这个附加信息的更新?对不起,我没注意到。有一件事我还不清楚,这阻碍了我回答这个问题,那就是,您有什么类型的其他存储库接口?在你的问题中,你陈述了1个iRepository,但GetRepo暗示还有很多其他的。“你能详细说明一下吗?也许能举个例子吗?”史蒂文我加上了我的单元测试,作为一个具体的例子,说明代码是如何使用的。谢谢你的回答。就像很多次你的答案出现在so或你的博客上一样,这就像打开了通往另一个世界的大门-由于您正试图将decorator应用于存储库,您可能希望阅读以下内容:特定于实体的存储库抽象可能是一件坏事,以及它们如何阻碍您使用decorator有效地应用横切关注点。
private Dictionary<Type, InstanceProducer> oracle;
private Dictionary<Type, InstanceProducer> sql;

public RepoProvider(
    Dictionary<Type, InstanceProducer> oracle, 
    Dictionary<Type, InstanceProducer> sql)
{
    this.oracle = oracle;
    this.sql = sql;
}

public T GetRepo<T>(bool oracle)  where T : class
{
    Dictionary<Type, InstanceProducer> repos = oracle ? this.oracle : this.sql;
    return (T)repos[typeof(T)].GetInstance();
}
container.RegisterSingleton<IRepoProvider>(new RepoProvider(
    oracle: new Dictionary<Type, InstanceProducer>
    {
        { typeof(ICarRepository), Lifestyle.Transient.CreateProducer<ICarRepository, OraCarRepository>(container) },
        { typeof(ITruckRepository), Lifestyle.Transient.CreateProducer<ITruckRepository, OraTruckRepository>(container) },
    },
    sql: new Dictionary<Type, InstanceProducer>
    {
        { typeof(ICarRepository), Lifestyle.Transient.CreateProducer<ICarRepository, SqlCarRepository>(container) },
        { typeof(ITruckRepository), Lifestyle.Transient.CreateProducer<ITruckRepository, SqlTruckRepository>(container) },
    });