【发布时间】:2009-04-09 11:21:21
【问题描述】:
我正在努力通过更多地了解依赖注入/IoC 和其他最佳实践方法来成为一名优秀的编程公民。为此,我有一个项目,我试图做出正确的选择并以“正确”的方式设计一切,无论这意味着什么。 Ninject、Moq 和 ASP.NET MVC 有助于提高可测试性并将应用程序“推出”。
但是,我有一个关于如何为我的应用程序所包含的对象设计实体基类的问题。我有一个简单的类库,网络应用程序建立在它之上。这个库公开了一个 IRepository 接口,默认实现(应用程序使用的那个)在幕后使用 Linq-to-SQL(DataContext 等不暴露给 Web 应用程序)并且只包含获取这些实体的方法。存储库基本上看起来像这样(简化):
public interface IRepository
{
IEnumerable<T> FindAll<T>() where T : Entity
T Get<T>(int id) where T : Entity
}
默认实现使用 DataContext 上的 GetTable() 方法来提供正确的数据。
但是,这要求基类“实体”具有一些特性。通过创建与 Linq-to-SQL 给我的映射对象同名的部分类,很容易让我的对象从它继承,但是“正确”的方法是什么?
例如,上面的接口有一个通过它的 id 获取实体的功能 - 所有从实体派生的不同类型的类确实都有一个 int 类型的“id”字段(从它们各自的主键映射表),但我怎样才能以一种让我像这样实现 IRepository 的方式指定它呢?
public class ConcreteRepository : IRepository
{
private SomeDataContext db = new SomeDataContext();
public IEnumerable<T> FindAll<T>() where T : Entity
{
return db.GetTable<T>().ToList();
}
public T Get(int id) where T : Entity
{
return db.GetTable<T>().Where(ent => ent.id == id).FirstOrDefault();
}
}
我是在无编译器的 PC 上从内存中执行此操作的,因此请原谅任何错误,希望您能理解我的意图。
这里的诀窍当然是要编译它,必须确定 Entity 承诺从它派生的每个人都有一个 id 字段。
我可以创建一个抽象字段,或者一个普通字段,它被 Linq-to-SQL 粘贴在生成的类中的 id 字段“隐藏”。
但这一切都感觉有点像作弊,甚至会给出编译器警告。
“Entity”是否真的应该是“IEntity”(一个接口),并且我应该尝试以 Linq-to-SQL 将实现的方式定义 id 字段?这也可以很容易地指定实体实现者需要实现的其他接口。
或者“实体”应该是一个带有抽象id字段的抽象基类,它是否也应该以抽象的方式实现所需的接口以供其他人覆盖?
我对 C# 的了解还不够,无法看到一个优雅的解决方案,所以我很想听听更有经验的系统设计师与一些基类经验权衡。
谢谢!
4 月 10 日编辑:
我知道我在这里遗漏了一些重要的东西。我的 IRepository 有两个具体的实现 - 一个是使用 LINQ to SQL 的“真实”实现,另一个是 InMemoryRepository,现在只使用 List,用于单元测试等。
添加的两种解决方案都适用于其中一种情况,而不适用于另一种情况。因此,如果可能的话,我需要一种方法来定义从 Entity 继承的所有内容都将具有“id”属性,并且这将与 LINQ to SQL DataContext 一起工作而不会“作弊”。
【问题讨论】:
标签: c# linq-to-sql oop