我有以下课程:
public class InMemoryRepository : IRepository
{
public void Add(object entity)
{
throw new NotImplementedException();
}
public void Attach(object Entity)
{
throw new NotImplementedException();
}
public T Get<T>(object id)
{
throw new NotImplementedException();
}
public IList<T> GetAll<T>(string queryName)
{
throw new NotImplementedException();
}
public IList<T> GetAll<T>()
{
throw new NotImplementedException();
}
public IQueryable<T> Query<T>()
{
throw new NotImplementedException();
}
public void Remove(object entity)
{
throw new NotImplementedException();
}
public void Save(object entity)
{
throw new NotImplementedException();
}
}
我们的默认存储库实现使用NHibernate作为后备存储,但我想实现它的内存版本,这样我就可以对域对象进行原型设计,而无需创建支持SQL数据库。假设所有对象都具有Id属性作为主键的约定,您将如何为此实现通用内存存储?
我很难解决一些关键问题:
Get<TestEntity>(object id)
应该能够查询所有存储的TestEntity实例并找到具有匹配Id属性的实例,但我无法直接定义TestEntity对象的集合,因为存储库不知道我是什么类型喂它直到运行时间。如何存储对象以满足上述要求?
答案 0 :(得分:5)
基础很简单:
public class InMemoryRepository : IRepository
{
private readonly IList<object> entities = new List<object>();
public T Get<T>(object id)
{
return entities.OfType<T>.SingleOrDefault(e => e.ID == id);
}
public IList<T> GetAll<T>()
{
return entities.OfType<T>.ToList();
}
public IQueryable<T> Query<T>()
{
return GetAll<T>.AsQueryable();
}
}
然而,一旦谈到public IList<T> GetAll<T>(string queryName)
,情况会变得复杂。
您可以使用基于SQLite的存储库实现进行测试。
答案 1 :(得分:2)
我会选择为in-memory SqlLite database配置的NHibernate。您可以测试您的真实代码,并确保一切正常。为存储库编写模拟可能很难,如果您更改IRepository
界面,则必须重新实现InMemoryRepository
。
对我来说,拥有NHibernate的一大好处是可以在内存数据库中进行测试。
答案 2 :(得分:2)
通过Anton的回答,我能够修复自己的InMemoryRepository。我修改了它以匹配问题中的类:
private readonly ConcurrentDictionary<Type, List<object>> ObjectList = new ConcurrentDictionary<Type, List<object>>();
public int Add<T>(T obj) where T : IIdentifier
{
// instantiate if list does not exist for this object type
if (!ObjectList.ContainsKey(typeof (T)))
ObjectList[typeof(T)] = new List<object>();
// get id
var id = GetId<T>() + 1;
// add object to list
obj.Id = id;
ObjectList[typeof(T)].Add(obj);
return id;
}
public void Attach<T>(T obj) {
// do not need to do anything
}
public T Get<T>(int id) where T : class, IIdentifier
{
// check list exist
if (!ObjectList.ContainsKey(typeof (T)))
return null;
return ObjectList[typeof(T)].OfType<T>().FirstOrDefault(n => n.Id == id);
}
public List<T> GetAll<T>(Func<T, bool> predicate) where T : new()
{
// check list exist
if (!ObjectList.ContainsKey(typeof(T)))
return null;
return ObjectList[typeof(T)].OfType<T>().Where(predicate).ToList();
}
public List<T> GetAll<T>()
{
return ObjectList[typeof(T)].OfType<T>.ToList();
}
public IQueryable<T> Query<T>()
{
return GetAll<T>.AsQueryable();
}
public int Remove<T>(int id) where T : IIdentifier
{
// check list exist
if (!ObjectList.ContainsKey(typeof(T)))
return 0;
// find object with matching id
for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == id)
{
ObjectList[typeof(T)].RemoveAt(i);
return id;
}
// object not found
return 0;
}
public int Save<T>(T obj) where T : IIdentifier
{
// check list exist
if (!ObjectList.ContainsKey(typeof(T)))
return 0;
// find object with matching id
for (var i = 0; i < ObjectList[typeof(T)].Count; i++)
if (ObjectList[typeof(T)].OfType<T>().ToList()[i].Id == obj.Id)
{
ObjectList[typeof (T)][i] = obj;
return obj.Id;
}
// object not found
return 0;
}
#region Helper methods
private int GetId<T>() where T : IIdentifier
{
return ObjectList[typeof(T)].Count == 0 ? 0 : ObjectList[typeof(T)].OfType<T>().Last().Id;
}
#endregion
答案 3 :(得分:1)