stackoverflow 上有几篇关于这个问题的帖子,但我仍然无法完全理解它。
\n提出了不同的架构,例如蓝皮书中的分层架构、端口和适配器、洋葱架构或清洁架构。尽管经过大量阅读后,我仍然不完全理解为什么提出了其他方法,但正如埃里克·埃文斯所假设的那样,每一种方法都隔离了领域。
\n在我的 Web API 项目中,我使用一个包含控制器的 Web API 层、一个处理和编排业务用例的应用程序层、域层以及一个使用 EF Core 实现存储库以访问数据库的持久层。API层调用处理程序处理的应用程序层的命令。稍后可能会为 GraphQL 或 gRPC 添加其他 API 层。
\nEric Evans 领域驱动设计:
\n\n\n“基础设施层通常不会在域层中发起操作。作为域层下方的\xe2\x80\x9c,它不应该\n对其所服务的域没有特定的了解。”
\n
我知道基础设施层通常不会在领域层发起操作,但我不明白它如何应该没有领域的具体知识。如果存储库不了解实体,它如何保存实体?
\nEric Evans 领域驱动设计:
\n\n\n应用程序层和域层调用基础设施层提供的服务。
\n
在 stackoverflow 上的其他帖子和文章中指出,领域层不应依赖于存储库或其他服务,而应用程序服务将访问这些服务并将结果提供给领域层。例如,应用程序命令处理程序将从存储库中按 id 获取聚合,然后调用该聚合上的域命令,然后更新存储库中的实体。
\n如果我对 Clean Architecture 和 Onion Architecture 的理解正确的话,域层位于中心,不访问任何外层。这与埃文斯矛盾还是只是一种改进?
\n我经常错过有关基础设施层中的关系的信息。考虑到不同的架构,我会认为我的 Web API 层是基础设施层的一部分。如果Web API控制器和存储库实现位于同一层,则API可以直接调用存储库并绕过应用程序服务。这对我来说毫无意义。我宁愿让 API 仅依赖于应用程序层。
\n\n在这种情况下,在域层中拥有存储库接口对我来说毫无意义。我会把它放在应用程序层。根据 Bob 叔叔的说法,该接口归客户端所有。因此,我将在应用程序层中拥有存储库接口。
\n通常,存储库接口是域层的一部分。这仅与不同的架构风格有关吗?如果我理解正确的话,在埃文斯方法中,域层可以访问基础设施,而在干净或洋葱架构中则不能。那是对的吗?
\n有人可以帮助我清除头脑中的混乱,并特别解释为什么使用哪种方法吗?在什么情况下域层调用基础设施有意义,在什么情况下不有意义?
\n我正在Optional<T>我的 DTO 中使用 Json Patch(详细信息)。类型 T 存储在类的“Value”字段中Optional<T>。Optional 类允许区分 null 和未提供。
public readonly struct Optional<T>
{
public Optional(T? value)
{
this.HasValue = true;
this.Value = value;
}
public bool HasValue { get; }
public T? Value { get; }
public static implicit operator Optional<T>(T value) => new Optional<T>(value);
public override string ToString() => this.HasValue ? (this.Value?.ToString() ?? "null") : "unspecified";
}
Run Code Online (Sandbox Code Playgroud)
我使用的第一个 DTO 仅包含原始类型,例如
public class PatchGroupDTO
{
public Optional<Guid?> SalesGroupId { get; init; } …Run Code Online (Sandbox Code Playgroud) 我正在努力解决一个基本问题。该项目是用 C# 编写的,但问题很普遍。
我遵循始终有效的对象原则。作为一个示例,我有一个具有强制属性“ProductCategory”的产品实体。允许的产品类别是用户定义的,因此会保留(在数据库中)。
为了类型安全和更好的阅读,我为各种属性定义了值对象来封装这些类型的业务规则。所以就有了一个ProductCategory类。创建 ProductCategory 实例时,工厂方法会检查创建实例之前传递给工厂的字符串的最大长度等。这确保了 ProdcutCategory 的每个实例都是有效的。
简单的参数检查(例如长度)既简单又直接。我的问题是在哪里对可能保留的值实施验证检查。允许值的存储库隐藏了持久性技术,并具有 Exists 或 IsValid 方法。
选项 1)在调用工厂之前从应用程序层调用存储库。
这里,领域层并不像许多人主张的那样依赖于存储库/基础设施层。但工厂无法再确保对象有效。业务规则的实现依赖于应用层。此外,每个需要 ProductCategory 的命令都必须检查存储库,这违反了 DRY。
选项 2)从值对象工厂调用存储库
由于工厂是域层的一部分,因此该层必须能够访问存储库,这会引入额外的耦合。好处是ProductCategory的业务有效性由对象本身保证,无法规避。
是否有其他解决方案可以解决这一困境,或者是否有任何具体标准鼓励其中一种或另一种选择?如果工厂是针对保存在领域层中的存储库接口进行编程并且仅由基础设施层中的存储库实现的,这样可以吗?我试图理解不同的方法,但在这种情况下我感到迷失。
c# validation domain-driven-design ddd-repositories user-defined
我想使用JSON Merge Patch支持部分更新支持部分更新。领域模型基于始终有效的概念,并且没有公共设置器。因此我不能只将更改应用于类类型。我需要将更改翻译为特定命令。
由于类具有可为 null 的属性,我需要能够区分设置为 null 的属性和未提供的属性。
我知道JSON Patch。我可以用来patch.JsonPatchDocument.Operations浏览更改列表。JSON Patch 只是冗长且对客户端来说更加困难。JSON Patch 需要使用Newtonsoft.Json(Microsoft 声明有一个选项可以更改Startup.ConfigureServices为仅用于Newtonsoft.JsonJSON Patch ( https://learn.microsoft.com/en-us/aspnet/core/web-api/jsonpatch?view=aspnetcore-6.0 )。
Newtonsoft 支持IsSpecified -Properties,可用作 DTO 类中 JSON Merge Patch 的解决方案(How to make Json.NET set IsSpecifiedproperty for property with complex values?)。这可以解决问题,但再次需要 Newtonsoft。System.Text.Json 不支持此功能。有一个长达 2 年的开放问题(https://github.com/dotnet/runtime/issues/40395),但没什么可期待的。
有一篇文章描述了用于 Web API 的自定义 JsonConverter 的解决方案( https://github.com/dotnet/runtime/issues/40395)。该解决方案仍然适用于 NetCore 吗?
我想知道在填充 DTO 对象后是否有一个选项可以访问原始 json或控制器方法内的 json 对象。然后我可以手动检查是否设置了属性。Web Api 关闭了流,因此我无法再访问正文。似乎有一些方法可以改变这种行为( …
对于 NetCore Web APIGET方法,我需要计算返回的 ETag List<T>。T 是 a 形式的 DTO record,仅保存原始类型。
我想计算列表的哈希值。我正在寻找有关如何GetHashCode()实施的信息,但找不到任何信息。object.GetHashCode()的文档
没有说明有关列表或集合的任何信息。通过代码的结果,我观察到每次运行时相同的列表数据都会创建不同的哈希码。我得出的结论是,GetHashCode()将指针值用于引用类型项。
GetHashCode()ofrecord计算每个成员值的哈希码。因此,我通过循环列表项创建了列表哈希代码:
List<GetGroupsDTO> dtoList = commandResult.Value;
int hash = 17;
foreach(GetGroupsDTO dto in dtoList)
{
hash = hash * 23 + dto.GetHashCode();
}
string eTagPayload = hash.ToString().SurroundWithDoubleQuotes();
Run Code Online (Sandbox Code Playgroud)
List<T>当然,我不想对每个人都这样做。我想覆盖GetHashCode(),但我正在努力解决。我不知道如何覆盖通用列表。我可以派生一个新类 DTOList ,我可以在其中重写GetHashCode(). 但这会导致其他地方变得更加复杂。由于 EFCore Set 查询的结果填充列表,我需要一个自定义转换器,然后需要一个自定义序列化器来返回 Web API 中的列表。
因此,我想知道是否应该为 List 创建一个扩展方法,或者只是一个以 List 作为参数的函数。还有其他选项可以计算 ETag 吗?如何有效计算 DTO 对象列表的 ETag?
c# ×3
architecture ×1
etag ×1
gethashcode ×1
json ×1
json-patch ×1
list ×1
repository ×1
swagger ×1
user-defined ×1
validation ×1