我正在尝试为我的应用程序编写一种可扩展的数据层其中一个“存储库”是我的抽象存储类的内存实现
public abstract class Store<TEntity, TIdentifier> : IStore<TEntity, TIdentifier>
where TEntity : StorableEntity<TIdentifier>
{
//abstract methods here
public abstract TIdentifier GetUniqueIdentifier();
}
“StorableEntity”抽象类是:
public abstract class StorableEntity<TIdentifier>
{
public TIdentifier ID { get; set; }
}
我有一个名为“InMemoryStore”的具体商店类,如下所示:
public class InMemoryStore<T, U> : Store<T, U>
where T : StorableEntity<U>
{
protected static Dictionary<U, T> store = new Dictionary<U, T>();
public override U GetUniqueIdentifier()
{
// call relevant "generator" here - SOMETHING LIKE THIS??
// var generator = GetGeneratorSomehow(U);
// return generator.Create();
}
}
现在,这里的“U”类型可以是string,int,Guid等...... (大多数时候它可能是int)
我的想法是创建像IUIDGenerator这样的东西:
public interface IUIDGenerator<T>
{
T Create(ICollection<T> collection);
}
在上面的“InMemoryStore”中,我将创建一个IUIDGenerator的实例,传入商店dictionarys密钥集合,并调用“Create”方法返回所需类型的唯一标识符。
例如,我可以有一个像这样的IntUIDGenerator类(它将作为一种增量数字生成器,基于字典键中已有的数字)
public class IntUIDGenerator : IUIDGenerator<int>
{
public int Create(ICollection<int> collection)
{
var result = collection.Max() + 1;
if (collection.Contains(result))
return result;
throw new NotUniqueException();
}
}
实际问题: 我需要做的是,在InMemoryStore中,识别U的类型(标识符的类型),并能够动态选择IUIDGenerator所需的具体实现 - 我该怎么做?
我想过有一种类工厂模式 - 将所有可用的UIDGenerator加载到字典中......但它们都可以有不同的类型?
有更好的解决方法吗?
此外,我知道我的问题的标题可能有点偏离 - 如果有人有更好的建议,请随时发表评论,我会改变它。
答案 0 :(得分:2)
您可以使用IoC框架,例如Unity,Castle,Ninject等。然后,您可以使用以下内容配置容器:
_container = new UnityContainer();
_container.RegisterType<IUIDGenerator<int>, IntUIDGenerator);
_container.RegisterType<IUIDGenerator<Guid>, GuidUIDGenerator);
然后在你的课堂上你会得到以下内容:
public override U GetUniqueIdentifier()
{
var generator = _container.Resolve<IUIDGenerator<U>>();
return generator.Create();
}
答案 1 :(得分:0)
我认为你必须使用至少一个演员表。如果您将所有生成器存储在地图中,如
Map<Type, object> generators;
你可以使用
class InMemoryStore<T,U> {
public override U GetUniqueIdentifier() {
var generator = generators[typeof(U)] as IUIDGenerator<U>;
return generator.Create(collection);
}
}
当然,我省略了所有类型的验证码:)(比如检查,如果类型U
的生成器在地图中等...)
答案 2 :(得分:0)
简答:使用dependency injection,让你的DI容器为你处理。
答案 3 :(得分:0)
您可以为生成器添加其他泛型类型参数,例如
public class InMemoryStore<T, U, V> : Store<T, U>
where T : StorableEntity<U>
where V : IUIDGenerator<U>, new() {
public override U GetUniqueIdentifier()
{
return (V)(Activator.CreateInstance<V>()).Create();
}
}