gpt4 book ai didi

c# - 规范模式实现帮助

转载 作者:搜寻专家 更新时间:2023-10-31 19:42:17 25 4
gpt4 key购买 nike

我有一个关于通过规范模式执行业务规则的问题。考虑以下示例:

public class Parent
{
private ICollection<Child> children;

public ReadOnlyCollection Children { get; }

public void AddChild(Child child)
{
child.Parent = this;
children.Add(child);
}
}


public class Child
{
internal Parent Parent
{
get;
set;
}

public DateTime ValidFrom;
public DateTime ValidTo;

public Child()
{
}
}

业务规则应该强制集合中不能有有效期与另一个有效期相交的 child 。

为此,我想实现一个规范,然后用于在添加无效子项时抛出异常,并且还可以用于在添加子项之前检查是否违反规则。

喜欢:


public class ChildValiditySpecification
{
bool IsSatisfiedBy(Child child)
{
return child.Parent.Children.Where(<validityIntersectsCondition here>).Count > 0;
}
}

但是在这个例子中, child 访问了 parent 。对我来说,这似乎不正确。当 child 尚未添加到 parent 时,该 parent 可能不存在。您将如何实现?

最佳答案

public class Parent {
private List<Child> children;

public ICollection<Child> Children {
get { return children.AsReadOnly(); }
}

public void AddChild(Child child) {
if (!child.IsSatisfiedBy(this)) throw new Exception();
child.Parent = this;
children.Add(child);
}
}

public class Child {
internal Parent Parent { get; set; }

public DateTime ValidFrom;
public DateTime ValidTo;

public bool IsSatisfiedBy(Parent parent) { // can also be used before calling parent.AddChild
return parent.Children.All(c => !Overlaps(c));
}

bool Overlaps(Child c) {
return ValidFrom <= c.ValidTo && c.ValidFrom <= ValidTo;
}
}

更新:

当然,规范模式的真正威力在于您可以插入和组合不同的规则。你可以有一个像这样的界面(可能有一个更好的名字):

public interface ISpecification {
bool IsSatisfiedBy(Parent parent, Child candidate);
}

然后在 Parent 上像这样使用它:

public class Parent {
List<Child> children = new List<Child>();
ISpecification childValiditySpec;
public Parent(ISpecification childValiditySpec) {
this.childValiditySpec = childValiditySpec;
}
public ICollection<Child> Children {
get { return children.AsReadOnly(); }
}
public bool IsSatisfiedBy(Child child) {
return childValiditySpec.IsSatisfiedBy(this, child);
}
public void AddChild(Child child) {
if (!IsSatisfiedBy(child)) throw new Exception();
child.Parent = this;
children.Add(child);
}
}

Child 会很简单:

public class Child {
internal Parent Parent { get; set; }
public DateTime ValidFrom;
public DateTime ValidTo;
}

并且您可以实现多个规范或复合规范。这是您的示例中的一个:

public class NonOverlappingChildSpec : ISpecification {
public bool IsSatisfiedBy(Parent parent, Child candidate) {
return parent.Children.All(child => !Overlaps(child, candidate));
}
bool Overlaps(Child c1, Child c2) {
return c1.ValidFrom <= c2.ValidTo && c2.ValidFrom <= c1.ValidTo;
}
}

请注意,使 Child 的公共(public)数据不可变(仅通过构造函数设置)更有意义,这样任何实例都不能以会使 无效的方式更改其数据父级

此外,考虑将日期范围封装在 specialized abstraction 中.

关于c# - 规范模式实现帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2158125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com