【问题标题】:C# Class Structure to Ensure Certain Filters Are Always Applied确保始终应用某些过滤器的 C# 类结构
【发布时间】:2017-09-30 02:03:42
【问题描述】:

因此,我目前正在与一个团队一起开展一个项目,我和我的团队遇到了一个特定的设计场景,我们正在尝试提出解决方案。

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

这个问题涉及我们解决方案中的三个主要项目:存储库、模型和服务项目。如果不清楚,每个项目的目的如下。 Models 项目包含我们存储在数据库中的所有数据的模型。 Repository 项目有一个主要的数据库访问类,它使用泛型与不同的表进行交互,具体取决于传入的模型。最后,Services 项目包含在前端之间接口数据的类-end 和存储库,通常每个服务类都一对一映射到模型类。正如人们所预料的那样,构建依赖项是:Repository 依赖于 Models,Services 依赖于这两个项目。

问题:

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

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

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

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

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

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

【问题讨论】:

  • 看过像 PostSharp 这样的面向方面的编程解决方案吗?
  • @KevinRaffay 我以前没有听说过这个,但是这个解决方案似乎涉及使用不同的编译器。我宁愿简单地尝试使用 C# 语言的上下文找到解决方案,而无需任何额外的接口。虽然 PostSharp 看起来很有趣,但我还是请与我一起工作的其他开发人员安装、学习和使用这个工具。

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


【解决方案1】:

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

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

最后,您还没有具体说明您的存储库在做什么,但是存储库应该非常简单,实际上只是返回所有对象的集合。像您所说的逻辑属于服务层。但是,即使这样也仅适用于使用 Dapper 或 ADO.NET 之类的东西进行直接数据库访问的情况。如果您使用的是像实体框架这样的成熟 ORM,请完全丢弃您的存储库层。是的,你没听错:完全扔掉它。包裹在 ORM 周围的存储库是一种无用的抽象,它只会添加更多需要维护和测试的代码,没有任何理由。服务层已经提供了某种程度的抽象给您带来的好处。

【讨论】:

  • 是的,我也是这么看待这项服务的。然而,我注意到在 ServiceA 以外的服务中访问 ModelA 数据的地方添加了很多代码。但是从您的回复中,我猜我不应该允许人们这样做,而是应该重写所有代码,以便仅在 ServiceA 中更改 ModelA 数据。同样关于 Repository 项目,我们似乎使用了几个不同的数据库/工具来与它们进行交互,因此据我了解,其中的类旨在使对所有数据库的访问更加一致。
  • @ShajeshJ 这也是服务层的工作。存储库应该只是原始 SQL 的抽象。其他任何事情都是滥用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多