2011-08-03 34 views
2

下面模型(右側)中的PartyRoleConstraints類是此問題的主題。泛型能改進這種設計嗎?

enter image description here

的想法是,當一個客戶端嘗試參加一個聚會,一個角色類型相關聯,該角色類型查看其是否有應防止某一締約方被相關的任何約束。締約方是個人和組織的超類型。

這裏是完全通用的接口,我以後:

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); 
    } 

的問題(!終於)是:我可以使用泛型以避免投,如果是這樣,怎麼樣?

回答

1

是的,你可以擺脫劇組,但你將不得不在某處指定「人物」。很難提出一個「最好的地方」這樣做,而不瞭解你的要求和限制。一個辦法是這樣的:

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

另一種選擇是tweek PartyRoleConstrainedToType允許進一步的限制。而例如可能是這樣的:

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

正如之前所說:你必須從某個地方指定Person,但有不同的選項來創建一個不錯語法。什麼好的意思,取決於你的要求和用例。

+0

我真的想知道是否可以使它成爲類類型參數的一部分,因爲這是跨越幾個應用程序的框架類型庫的一部分。沒有想到一般的流利類型的東西,這正是我想你所說的。那對於是一個嵌套類?你可以添加幾行代碼來幫助我更好地看到它嗎? – Berryl

+0

子類化給定的約束,比如ie,新的MustMatchGender(Gender.Male)對於給定域中的更常見的約束可能是最好的,但是想要更好地理解你提出的更好的約束。乾杯 – Berryl