下面模型中的PartyRoleConstraints类(右侧)是这个问题的主题。
我们的想法是,当客户端尝试将Party与RoleType关联时,RoleType会查看是否存在任何会阻止给定Party关联的约束。党是个人和组织的超级类型。
这是我追求的完全通用的界面:
public interface IRoleConstraint<in T>
{
Func<T, bool> IsSatisfied { get; }
string UnsatisfiedDescription { get; }
bool CanAddRole(T instance);
}
常见的约束是Type。所以,如果我有“丈夫”的角色类型,那么我想确保Party实例是一个人。以下是一些实现和一个测试用例,证明我可以这样做:
public class RoleConstraint<T> : IRoleConstraint<T>
{
public RoleConstraint(Func<T, Boolean> isSatisfied, string unsatisfiedDescription) {
if (isSatisfied == null) throw new ArgumentNullException("isSatisfied");
if (unsatisfiedDescription == null) throw new ArgumentNullException("unsatisfiedDescription");
IsSatisfied = isSatisfied;
UnsatisfiedDescription = unsatisfiedDescription;
}
public Func<T, bool> IsSatisfied { get; protected set; }
public string UnsatisfiedDescription { get; protected set; }
public bool CanAddRole(T instance) { return IsSatisfied.Invoke(instance); }
}
public class PartyRoleConstraint : RoleConstraint<Party>
{
public PartyRoleConstraint(Func<Party, bool> isSatisfied, string unsatisfiedDescription) : base(isSatisfied, unsatisfiedDescription) { }
}
public class PartyRoleConstrainedToType<TRequired> : PartyRoleConstraint where TRequired : Party
{
private static readonly string _unsatisfiedDescription
= string.Format("This role requires a Party instance to be a {0}", typeof(TRequired).Name);
private static readonly Func<Party, bool> _isSatisfied = instance => instance.GetType().Equals(typeof(TRequired));
public PartyRoleConstrainedToType() : base(_isSatisfied, _unsatisfiedDescription) { }
}
[Test]
public void Constraints_IfTypeConstraint_and_InstanceDoesNotMatch_False()
{
var sony = new Organization("Sony Corporation");
var constraint = new PartyRoleConstrainedToType<Person>();
_husbandRoleType.AddConstraint(constraint);
Assert.That(_husbandRoleType.CanAddRole(sony), Is.False);
}
我遇到的问题是我是否想要根据Party子类的属性设置规则。例如,我希望丈夫的性别是男性。我可以用演员表来做到这一点:
[Test]
public void Constraints_IfConstraintConditionIsNotMet_False()
{
_husbandRoleType.AddConstraint(new PartyRoleConstrainedToType<Person>());
Assert.That(_husbandRoleType.CanAddRole(_arthur), Is.True);
//**** here is the cast **** //
var mustBeMale = new PartyRoleConstraint(p => ((Person)p).Gender == Gender.Male, "the husband must be male.");
_husbandRoleType.AddConstraint(mustBeMale);
Assert.That(_husbandRoleType.CanAddRole(_arthur), Is.False);
_arthur.Gender = Gender.Male;
Assert.That(_husbandRoleType.CanAddRole(_arthur), Is.True);
}
问题(终于!)是:我可以使用泛型来避免演员表,如果是,那该怎么办?
答案 0 :(得分:1)
是的,你可以摆脱演员阵容,但你必须在某处指定“人物”。在不了解您的要求和约束的情况下,很难提出这样做的“最佳位置”。一种选择是:
var mustBeMale = PartyRoleConstraint.For<Person>( p => p.Gender == ...);
另一个选择是调整PartyRoleConstrainedToType
以允许进一步的限制。示例可能如下所示:
var combinedConstraint = new PartyRoleConstrainedToType<Person>().MustSatisfy(p => p.Gender == ...);
如前所述:您必须在某处指定Person
,但有一些不同的选项可用于创建 nice 语法。什么好的意思,取决于您的要求和用例。