用于确保始终应用某些过滤器的C#类结构

时间:2017-09-29 17:20:41

标签: c# oop design-patterns asp.net-mvc-5

所以我目前正在与一个团队合作开展一个项目,而我和我的团队遇到了一个我们正试图想出一个解决方案的设计方案。

当前项目实施的背景信息:

此问题涉及我们解决方案中的三个主要项目:存储库,模型和服务项目。如果不是很明显,每个项目的目的如下。 模型项目包含我们存储在数据库中的所有数据的模型。 存储库项目有一个主数据库访问类,它使用泛型与不同的表进行交互,具体取决于传入的模型。最后,服务项目包含在前面连接数据的类-end和repository,通常每个服务类将1对1映射到模型类。正如人们所料,构建依赖关系是:Repository依赖于Models,而Services依赖于这两个项目。

问题:

我们遇到的当前问题是我们需要一种方法来确保如果开发人员尝试查询或与特定类型的对象交互(称之为ModelA),那么我们需要确保一组特定的过滤器是默认情况下始终包含(并且这些过滤器部分基于特定用户是否有权查看列表中的某些对象)。开发人员应该能够覆盖此过滤器。

我们要避免做的是在存储库类中使用if子句,如果您要更新此模型类型,请添加这些过滤器"。

我们已经考虑/考虑的解决方案:

我们目前正在考虑的一个解决方案是在ServiceA中使用一个函数(与ModelA相对应的服务),将这些过滤器附加到给定查询,然后使其成为如果有人请求模型的db上下文,必须传递一个以某种方式操作过滤的函数(换句话说,如果他们想要与ModelA交互,他们将传递来自ServiceA的过滤器函数)。此解决方案的问题是开发人员需要始终意识到,如果他们与ModelA进行交互,他们必须从ServiceA传入该功能。另外,因为我们不希望每个模型都强制执行某些过滤器选项,所以我们可能希望这是一个可选参数,这可能会导致开发人员在与ModelA交互时忘记包含此函数的问题。

我们考虑的另一个解决方案是在ModelA上有一个属性(让我们称之为DefaultFilterAttribute),它存储一个应该实现特定接口的类类型(称为IFilterProvider)。 ServiceA将实现此接口,ModelA的属性将作为类型提供给ServiceA。然后,存储库方法可以检查传入的实体是否具有DefaultFilterAttribute,然后只需调用附加到该属性的类实现的方法。不幸的是,正如你们中的一些人可能已经注意到的那样,我们的项目依赖项目前的设置方式,我们无法真正实现这样的解决方案。

所以我想知道这个问题是否有一个干净的解决方案,或者我们是否可能错误地考虑问题和/或设计模式,并且应采取完全不同的方法。

1 个答案:

答案 0 :(得分:0)

我认为你正在使这种不必要的复杂化。您所描述的几乎是服务层的全部目的。据推测,你有GetModelAList之类的东西(对于服务而言,这实际上是一种非常糟糕的方法,但仅仅是为了说明)。然后,自动应用某些过滤器的逻辑被封装在该方法中。应用程序不知道或关心如何检索数据;它只知道它是否需要一个ModelA实例列表,它会调用该方法。

如果您想要一种不应用这些过滤器的方法,可以提供另一种方法,例如GetModelAListUnfiltered,或者将布尔值或其他内容传递给确定是否自动应用过滤器的原始方法。真的,你可以随心所欲地处理这个问题,但重点是它已经封装在你的服务中。

最后,您尚未准确指定存储库正在执行的操作,但存储库应该非常简单,实际上只返回所有对象的集合。像你所说的那样的逻辑属于服务层。但是,即使这只适用于您使用Dapper或ADO.NET等直接进行数据库访问的情况。如果您正在使用像Entity Framework这样的完整ORM,请完全丢弃您的存储库层。是的,你没听错我的意思:把它扔掉。围绕ORM的存储库是一种无用的抽象,仅用于添加更多需要维护和测试的代码,没有任何理由。服务层已经提供了某种抽象级别所带来的好处。