以下のモデル(右)のPartyRoleConstraintsクラスがこの質問の対象です。ジェネリックはこのデザインを改善できますか?
アイデアは、クライアントがRoleTypeでパーティーを関連付けるしようとすると、それが関連しているから与えられたパーティーを防ぐ必要がある任意の制約を持っている場合、RoleTypeが見ているということです。パーティーは、個人と組織の両方のスーパータイプです。一般的な制約はタイプによってだろう
public interface IRoleConstraint<in T>
{
Func<T, bool> IsSatisfied { get; }
string UnsatisfiedDescription { get; }
bool CanAddRole(T instance);
}
:
はここで後に私は完全に一般的なインタフェースです。だから私は "夫"の役割のタイプを持っている場合、私はパーティーのインスタンスが人であることを確認したい。ここで私はこれを行うことができます証明いくつかの実装とテストケースである:私は党のサブタイプの属性に基づいてルールを設定したい場合は
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);
}
私は当たっています問題があります。たとえば、私は夫の性別を男性にします。私のように、キャストでこれを行うことができます。
[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);
}
質問(ついに!)である:私はキャストを避けるために、ジェネリックを使用し、そうであれば、どのようにできますか?
これは、いくつかのアプリケーションにまたがるフレームワークタイプのlibの一部であるため、私は実際にクラスタイプのparamsの一部にすることができるのだろうかと思っていました。一般的な流暢なタイプのものは考えていませんでした。それはあなたが言っていると思います。それはのために入れ子にされたクラスですか?あなたがそれをより良く見るのを助けるために、いくつかの行のコードを追加してください。 –
Berryl
例えば、新しいMustMatchGender(Gender.Male)のような与えられた制約をサブクラス化することは、特定のドメインでより一般的な制約に最も適していますが、より良い提案も理解したいと思います。乾杯 – Berryl