2010-11-19 94 views
1

自从我使用接口协方差的最后一个问题以来,我还没有遇到代码问题。今天,我采取了另一种方法来OLGAtherer架构,我发现巨大的(对我来说)障碍。我希望它的巨大的只有我,我会找到答案在这里:) OK,请检查了这一点:如何指向泛型抽象类?

我有抽象泛型类:

abstract class Repository<T> where T : Entity 

这个类包含四种CRUD方法签名(加,插入等)和两个受保护的字段。我将创建的任何存储库都必须从此超类继承。我有一个像仓库,例如:

class BookRepository : Repository<Book> 

现在我有DB类是负责对DB文件操作。这是我的问题。看看这个方法放在DB类:

void Add(List<Entity> enitites, Type entityType) 
    { 
     Repository<entityType> repo = EntitiesFactory(entityType); 
     repo.Add(entities); 
    } 

我知道,上面的方法都不行,但是这个想象我的问题(希望) - 我想动态地创建指定类型的仓库,但我有不知道如何做到这一点。这一直是我的主要OOP问题 - 我可以编写继承(或接口的实现),但我不能使用这些继承的类。请向我澄清一下。先谢谢你。

帕维尔


我用你提供的线索,这就是我现在:现在

public void Add<T>(List<T> entities, string repoName) where T : Entity 
{ 
    Repository<T> repo = RepoFactory<T>(repoName, typeof(T)); 
    repo.Add(entities); 
} 

private Repository<T> RepoFactory<T>(string repoName, Type t) where T : Entity 
{ 
    if (t == typeof(Book)) 
    { 
    Repository<T> repo = (Repository<T>)((object)(new BookRepository(this.ConnectionString, repoName))); 
    } 

    return null; 

}

RepoFactory是DB类(这是由方式,在这里某种桥梁) - 它应该移动到其他地方,但这不是一个主要问题。

首先,我不知道RepoFactory体是否以正确的方式实现 - 我想不是。

第二 - 我假设我会从其他类调用DB方法(比方说 - WindowsForm,为简单起见)。我将根据用户的选择调用添加参数T.这是我有问题并暂时修复它的情况,因为现在DB是可以的,但是如果我必须实现WindowsForm代码,我会再次遇到它(我认为) - 将来我会试着找出答案同样的问题,但在更高的层次上(DB以上) - 我希望你明白我... 我基本上是说,我不会知道如何动态调用添加方法,因为T将取决于用户的选择(OLGAtherer有成为Repository Manager,可以支持书籍和其他类型的集合)。如果用户尝试使用他的书集,我将不得不调用Add()方法。如果使用Comics集合,则添加()。我不想为每种类型的集合编写类,而是使用Add的一个调用来执行此操作。

如果你明白我的意思,你真的很好:)我的英语很烂,但我正在努力。 感谢您提供以前的答案,并提前感谢您提供更多答案。 Paweł

+1

嗯,我想你想重新发明轮子。为什么当你有很多已经很好开发的替代品如NHibernate和Linq2Sql时,你可以编写自己的ORM? – Juliet 2010-11-19 20:01:20

+0

'DB'听起来像一个上帝对象,'EntitiesFactory'听起来像一个服务定位器。你正在为自己设定一个无法维护的,不可测试的灾难。 – jason 2010-11-19 20:49:00

+0

你好,我知道这可能看起来不是一个好主意 - 我仍然在学习,我知道OOP的掌握需要花费数年的时间。但是如果你看看我放在Sourceforge上的代码,我认为你会接受我创建的架构。无论如何,谢谢您的回复。 – skrzeczowas 2010-11-20 20:03:48

回答

7

我不太清楚你想要什么。这会做什么?

void Add<T>(List<T> entities) where T : Entity 
{ 
    Repository<T> repo = EntitiesFactory(typeof(T)); 
    repo.Add(entities); 
} 

此外,我建议你尽可能灵活地使用输入参数,例如,使用IEnumerable<T>而不是List<T>用于此方法以及Repository<T>.Add()方法。您可能想要传入延迟评估的查询,或将多个LINQ方法链接在一起。

+0

+1正是我要回答的。 – Sorax 2010-11-19 19:54:42

+0

哇。任何时候,我不知道该怎么做,我无法在任何地方找到答案,我知道我可以在这里发帖,我一定会得到答案!感谢您的这些以及关于释放依赖关系的有用提示。我想问你读下面我的新帖子 - 这个问题的下一部分:)最好的问候,Paweł – skrzeczowas 2010-11-20 20:39:40

3

您可以使Add方法通用。

void Add<T>(List<T> enitites) 
{ 
    Repository<T> repo = EntitiesFactory(typeof(T)); 
    repo.Add(entities); 
} 
+0

是的,这是:) – skrzeczowas 2010-11-20 20:40:01

2

如下你可以把它的类型安全通过一个间接更多层的改你的对象hiearchy:

public abstract class EntityCollection<T> : List<T> 
    where T : Entity 
{ 
    public abstract Repository<T> GetRepository(); 
} 

public class BookCollection : EntityCollection<Book> 
{ 
    public override Repository<Book> GetRepository() 
    { 
     return BookRepository(); 
    } 
} 

所以现在你可以修改你的数据库类,如下所示:

public void Add<T>(EntityCollection<T> entities) 
{ 
    Repository<T> repo = entities.GetRepository(); 
    repo.Add(entities); 
} 

所以现在您可以将BookCollection的实例传递给您的Add方法,并且它将以100%类型安全,透明的方式工作。

+0

我不知道这是否正是你要找的答案,但它更好地保持它类型安全,而不是严重依赖铸件和型式试验。如果你不得不打开一个泛型类型参数,你做错了什么。 – Juliet 2010-11-19 20:13:01

+0

朱丽叶,你说的肯定是对的,但实际上我问了上面的问题,因为我不知道如何切换。如果你能告诉我该怎么做不使用开关会很好。 – skrzeczowas 2010-11-20 21:00:58

2

只需添加到其他人的答案中,您也可以查看控制反转(IoC)设计模式。它可能会在未来的工作中简化你的生活。例如,使用IoC为您提供的依赖注入,您可以显着简化对EntitiesFactory的使用。

我现在使用StructureMap来实现IoC,它对我来说工作的很好。

Here is Martin Fowler's page on IoC,and Wikipedia's,让你开始。

+0

谢谢你的回答!我很高兴在这里得到这么多有用的信息。 – skrzeczowas 2010-11-20 20:44:13

1

无论你回来EntitiesFactory()是你需要使用。所以这个问题真的与你没有显示的代码有关。显示EntitiesFactory()的代码,我们可以更好地了解您要完成的任务。

注意:您知道您不能重载返回类型(不幸)。

+0

不幸的是,我在上面的Add方法中编写的代码是某种“伪代码”。我的意思是,这是我想如何工作:)请阅读下面的帖子。无论如何谢谢你的回答。 – skrzeczowas 2010-11-20 21:02:51