型指定されたDataSetを利用したドメインモデル

.NET2.0で型指定されたDataSetにPartialクラスで拡張できるのを利用してドメインロジックを型指定されたDataSetに追加することができる。
以前外部メソッド(Foreign Method)で実装していたが、これに比べて少し変わる程度かなと思っていたが、直感的ですごく良い感じ。ドメインモデルなんてという人でも受けて入れてもらえそう。


  • 新Partialクラス版
partial class RentalTitleRow
{
    public int ReservationCount
    {
        get 
        {
            return this.GetReservationRows().Length;
        }
    }

    public int RentalCount
    {
        get 
        {
            int count = 0;
            foreach (RentalModelData.RentalItemRow itemRow
                         in this.GetRentalItemRows())
            {
                if (itemRow.IsRented) count++;

            }
            return count;
        }
    }

    public int RentalItemCount
    {
        get 
        {
            return this.GetRentalItemRows().Length;
        }
    }

    public int CurrentStockCount
    {
        get
        {
            return RentalItemCount - RentalCount;
        }

    }

    public int CurrentRentableCount
    {
        get 
        {
            return CurrentStockCount - ReservationCount;
        }
    }

    public bool IsRentableForUser(UserRow aUser)
    {
        if (aUser.IsReservedTitle(this)) return true;
        if (this.RentalRuleRow.Disable) return false;
        if (this.RentalRuleRow.MemberOnly && !aUser.IsMember) return false;
        if (this.CurrentRentableCount <= 0) return false;
        return true;
    }
}
  • 旧外部メソッド版
public class RentalTitleHelper
{
	private RentalModelData context;
	public RentalTitleHelper(RentalModelData context)
	{
		this.context = context;
	}

	public int ReservationCount(RentalModelData.RentalTitleRow row)
	{
		return row.GetReservationRows().Length;
	}

	public int RentalCount(RentalModelData.RentalTitleRow row)
	{
		int count = 0;
		RentalItemHelper helper =  new RentalItemHelper(context);
		foreach (RentalModelData.RentalItemRow itemRow
					 in row.GetRentalItemRows())
		{
			if (helper.IsRented(itemRow)) count++;
			
		}
		return count;
	}

	public int RentalItemCount(RentalModelData.RentalTitleRow row)
	{
		return row.GetRentalItemRows().Length;
	}

	public int CurrentStockCount(RentalModelData.RentalTitleRow row)
	{
		return RentalItemCount(row) -  RentalCount(row);
	}

	public int CurrentRentableCount(RentalModelData.RentalTitleRow row)
	{
		return CurrentStockCount(row) - ReservationCount(row);
	}

}

public class RentableTitleValidation : ITitleValidation
{
	private RentalModelData context;
	private RentalModelData.UserRow _user;

	public RentableTitleValidation(RentalModelData context,
		RentalModelData.UserRow aUser)
	{
		this.context = context;
		this._user = aUser;
	}

	public bool IsSatisfied(RentalModelData.RentalTitleRow title)
	{
		RentalTitleHelper aRentalTitleHelper = new RentalTitleHelper(context);
		UserHelper aUserHelper = new UserHelper(context);
		if (aUserHelper.IsReservedTitle(_user, title)) return true;
		if (title.RentalRuleRow.Disable) return false;
		if (title.RentalRuleRow.MemberOnly 
                   && !aUserHelper.IsMember(_user)) return false;	
		if (aRentalTitleHelper.CurrentRentableCount(title) <= 0) return false;				
		return true;
	}
}