Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 泛型可以改进这种设计吗?_C#_Generics - Fatal编程技术网

C# 泛型可以改进这种设计吗?

C# 泛型可以改进这种设计吗?,c#,generics,C#,Generics,下面模型中的PartyRoleConstraints类(右侧)是这个问题的主题 其思想是,当客户机试图将一方与角色类型相关联时,角色类型会查看它是否有任何约束,这些约束应阻止将给定的一方关联起来。政党是个人和组织的超级类型 这是我想要的完全通用的界面: public interface IRoleConstraint<in T> { Func<T, bool> IsSatisfied { get; } string UnsatisfiedDescript

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

其思想是,当客户机试图将一方与角色类型相关联时,角色类型会查看它是否有任何约束,这些约束应阻止将给定的一方关联起来。政党是个人和组织的超级类型

这是我想要的完全通用的界面:

public interface IRoleConstraint<in T>
{
    Func<T, bool> IsSatisfied { get; }
    string UnsatisfiedDescription { get; }
    bool CanAddRole(T instance);
}
公共接口IRoleConstraint
{
Func已满足{get;}
字符串未满足说明{get;}
boolcanaddrole(T实例);
}
常见的约束是按类型。因此,如果我的角色类型是“丈夫”,那么我希望确保Party实例是Person。下面是一些实现和一个测试用例,证明我可以做到这一点:

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);
    }
公共类角色约束:IRoleConstraint
{
公共角色约束(函数已满足,字符串未满足描述){
如果(IsSatified==null)抛出新的ArgumentNullException(“IsSatified”);
如果(unsatifieddescription==null)抛出新ArgumentNullException(“unsatifieddescription”);
Issatified=Issatified;
未满足描述=未满足描述;
}
公共函数已满足{get;protected set;}
公共字符串未满足说明{get;protected set;}
公共boolcanaddrole(T实例){return issatified.Invoke(实例);}
}
公共类PartyRoleConstraint:角色约束
{
public PartyRoleConstraint(函数已满足,字符串未满足描述):基(已满足,未满足描述){
}
公共类partyroleconstrained类型:partyroleconstrained所需位置:Party
{
私有静态只读字符串\u未满足说明
=string.Format(“此角色要求参与方实例为{0}”,typeof(TRequired.Name);
private static readonly Func_issatified=instance=>instance.GetType().Equals(typeof(TRequired));
public PartyRoleConstrainedToType():基(_已满足,_未满足描述){
}
[测试]
公共无效约束\u IfTypeConstraint\u和\u InstanceDoesNotMatch\u False()
{
var sony=新组织(“索尼公司”);
var constraint=new PartyRoleConstrainedToType();
_husbandRoleType.AddConstraint(约束);
Assert.That(_husbandRoleType.CanAddRole(索尼)是.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);
    }
[测试]
公共无效约束\u ifConstraintConditionsNotSet\u False()
{
_AddConstraint(新PartyRoleConstrainedToType());
Assert.That(_husbandRoleType.CanAddRole(_亚瑟),是.True);
//****这是演员阵容****//
var mustBeMale=新的PartyRoleConstraint(p=>((Person)p)。Gender==Gender.Male,“丈夫必须是男性。”);
_husbandRoleType.AddConstraint(必须为男性);
Assert.That(_husbandRoleType.CanAddRole(_亚瑟),是.False);
_亚瑟。性别=性别。男性;
Assert.That(_husbandRoleType.CanAddRole(_亚瑟),是.True);
}

问题(最后!)是:我可以使用泛型来避免这种类型转换吗?如果可以,如何避免?

是的,您可以取消该类型转换,但您必须在某个地方指定“Person”。在不了解更多需求和约束的情况下,很难提出这样做的“最佳地点”。一种选择是:

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

如前所述:您必须在某个地方指定
Person
,但是有不同的选项来创建一个好的语法。nice的含义取决于您的需求和用例。

我实际上想知道是否可以将其作为类类型params的一部分,因为这是将跨越几个应用程序的框架类型库的一部分。我没想到会有一种通俗流畅的东西,我猜你是这么说的。这是用于嵌套类的吗?你能添加几行代码来帮助我更好地理解它吗?子类化一个给定的约束,如ie,new MustMatchGender(Gender.Male)可能最适合于给定域中更常见的约束,但我也想更好地理解你的建议。干杯
var combinedConstraint = new PartyRoleConstrainedToType<Person>().MustSatisfy(p => p.Gender == ...);