我在我的C#WinForms应用程序中使用SimpleInjector。 我需要在运行时决定访问哪个存储库(Oracle或SqlServer),因为这取决于他想要连接到哪个数据库的用户。 目前我这样做了,一旦我为存储库添加了一个Decorator就会失败。
_container.RegisterCollection<IRepository>(
new[] { typeof(OraRepository), typeof(SqlRepository) });
并且为了区分使用哪一个,我使用这样的提供者类:
public T GetRepo<T>(bool oracle)
where T : class
{
var instances = _container.GetAllInstances<T>();
if (oracle)
{
return instances.First(i => i.GetType().Name.StartsWith("Ora"));
}
else
{
return instances.First(i => !i.GetType().Name.StartsWith("Ora"));
}
}
我不想为每个数据库添加装饰器。此外,似乎不可能,因为没有RegisterDecoratorCollection
; - )
我的肚子告诉我,依靠上面所示类型的字符串名称是不对的。 该如何正确完成?
编辑:
有关使用场景的更多高级信息:
我的单位测试:
[TestInitialize()]
public void MyTestInitialize()
{
var container = new SimpleInjector.Container();
... other dependencies ...
container.RegisterCollection<ICarRepository>(
new[] { typeof(OraCarRepository), typeof(SqlCarRepository) });
container.RegisterCollection<ITruckRepository>(
new[] { typeof(OraTruckRepository), typeof(SqlTruckRepository) });
_provider = new RepoProvider(container);
}
运行测试:
[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());
}
答案 0 :(得分:1)
您的问题实际上并不容易回答。
我的肚子告诉我,依靠上面所示类型的字符串名称是不对的。该如何正确完成?
根据您当前的设计,我可以想象将您的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) },
});
这允许您在不破坏系统的情况下应用装饰器。