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