仿制药可以改进这种设计吗?

时间:2011-08-03 18:38:48

标签: c# generics

下面模型中的PartyRoleConstraints类(右侧)是这个问题的主题。

enter image description here

我们的想法是,当客户端尝试将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);
    }

问题(终于!)是:我可以使用泛型来避免演员表,如果是,那该怎么办?

1 个答案:

答案 0 :(得分:1)

是的,你可以摆脱演员阵容,但你必须在某处指定“人物”。在不了解您的要求和约束的情况下,很难提出这样做​​的“最佳位置”。一种选择是:

var mustBeMale = PartyRoleConstraint.For<Person>( p => p.Gender == ...);

另一个选择是调整PartyRoleConstrainedToType以允许进一步的限制。示例可能如下所示:

var combinedConstraint = new PartyRoleConstrainedToType<Person>().MustSatisfy(p => p.Gender == ...);

如前所述:您必须在某处指定Person,但有一些不同的选项可用于创建 nice 语法。什么好的意思,取决于您的要求和用例。