我一直试图想出一种方法来编写针对各种数据存储的通用存储库:
public interface IRepository { IQueryableGetAll (); void Save (T item); void Delete (T item); } public class MemoryRepository : IRepository {...} public class SqlRepository : IRepository {...}
我想在每个中使用相同的POCO域类.我也在考虑类似的方法,每个域类都有自己的存储库:
public interface IRepository{ IQueryable GetAll(); void Save(T item); void Delete(T item); } public class MemoryCustomerRepository : IRepository {...} public class SqlCustomerRepository : IRepository {...}
我的问题:1)第一种方法是否可行?2)第二种方法是否有任何优势.
第一种方法是可行的,在我编写自己的映射框架时,我已经做了类似的事情,该框架针对RDBMS和XmlWriter
/ XmlReader
.您可以使用这种方法来简化单元测试,但我认为现在我们拥有优秀的OSS工具来实现这一目标.
第二种方法是我目前使用的IBATIS.NET映射器.每个映射器都有一个接口,每个映射器[都]可以提供基本的CRUD操作.优点是域类的每个映射器还具有由接口表示并在具体映射器中定义的特定函数(例如SelectByLastName
或DeleteFromParent
).因此,我不需要像你建议的那样实现单独的存储库 - 我们的具体映射器以数据库为目标.为了执行单元测试,我使用StructureMap和Moq来创建作为您的存储器运行的内存存储库Memory*Repository
确实.它实现和管理的类较少,而且对于一种非常可测试的方法而言整体工作较少.对于跨单元测试共享的数据,我为每个具有WithXXX
方法和AsSomeProfile
方法的域类使用构建器模式(AsSomeProfile
只返回具有预配置测试数据的构建器实例).
这是我在单元测试中通常最终得到的一个例子:
// Moq mocking the concrete PersonMapper through the IPersonMapper interface var personMock = new Mock(MockBehavior.Strict); personMock.Expect(pm => pm.Select(It.IsAny ())).Returns( new PersonBuilder().AsMike().Build() ); // StructureMap's ObjectFactory ObjectFactory.Inject(personMock.Object); // now anywhere in my actual code where an IPersonMapper instance is requested from // ObjectFactory, Moq will satisfy the requirement and return a Person instance // set with the PersonBuilder's Mike profile unit test data