RIA Serviceのファーストインプレッション

一言でいうとフレームワークというよりはLOBアプリケーションプラットホーム。
実務的なところは好感がもてるが、ただ少しごちゃごちゃしている感じがしている。RoRなどと同じにおいがする。
「"Good enough" is good enough.」という感じです。

サービス(サーバー)処理の実行

ドメインサービスの実行は非同期になります。非同期処理時の画面制御も面倒かなと思っていましたが、テンプレートメソッドとBusyIndicatorの組み合わせで特に大変さはありませんでした。

//非同期のLoad処理を実行して正常終了時には以後の処理を行う
ExecuteAsync(shopContext.Load(shopContext.GetShopQuery(ShopId)),
      (x) => OrderData.OrderShop = shopContext.Shops.FirstOrDefault());

public void ExecuteAsync(OperationBase operation, Action<OperationBase> complateAction, Action<OperationBase> errorAction = null)
{
    if (complateAction == null) throw new ArgumentNullException("complateAction");
    IsBusy = true; 
    operation.Completed += delegate {
        try {
            if (operation.HasError || operation.IsCanceled) {
                if (errorAction != null) errorAction(operation);
            } else {
                complateAction(operation);
            }
        } finally {
            IsBusy = false;
        }
    }
}

画面遷移

画面遷移はSilverlightのPageクラスを使ったものですが、いくつかのイベントをハンドリングすることでPage移動時に閉じるの確認やキャンセルを行うことが簡単にできました。

private void ContentFrame_Navigating(object sender, NavigatingCancelEventArgs e)
{
    var current = DataContext as AppViewModel;
    if (current != null) {
        var arg = new CancelEventArgs();
        current.OnClosing(arg);  //ViewModelのOnClosingを呼び出し確認する
        if (!e.Cancel && arg.Cancel) e.Cancel = true;
    }
}
public override void OnClosing(CancelEventArgs arg)
{
    if (ProductList.HasChanges) {
        if (!this.ShowOKCancel("Do you discard changes?")) {
            arg.Cancel = true;
        }
    }
}

入力検証

入力検証はDataAnnotations属性を使う方法で行いました。ValidationSummaryと組み合わせてそのまま業務アプリでも使えそうです。

[Required]
[Range(1, 10)]
public int Amount
{
    get { return _amount; }
    set { ValidateProperty("Amount", value); _amount = value; }
}
public int _amount;

ValidationSummaryのHasErrorsをViewModelでバインドするとViewModelでViewの入力エラー状態を簡単に検知できました。

        <dataInput:ValidationSummary  Grid.Row="2" x:Name="summary" HasErrors="{Binding Path=HasError, Mode= TwoWay}"  />

モデル

Entity Frameworkで作成したモデルを自動生成してクライアントでも利用できるようにしてくれます。Entityクラスからの派生でINotifyPropertyChangedも実装してくれて便利です。

//サーバー側のオリジナル
public partial class Order
{
    [Key]
    public int ID { get; set; }
    public DateTime OrderDateTime { get; set; }
    public decimal TotalPrice { get; set; }
    public int ShopID { get; set; }
    [Include]
    [Association("Order_Shop", "ShopID", "ID")]
    public Shop OrderShop { get; set; }
    [Include]
    [Association("Order_OrderItem", "ID", "OrderID")]
    public ICollection<OrderItem> Items { get; set; }
}
//生成されたコード(一部)
[DataContract(Namespace="http://schemas.datacontract.org/2004/07/ViewMaker.Samples.BurgerShop.Web.Models")]
public sealed partial class Order : Entity
{
    [DataMember()]
    [Editable(false, AllowInitialValue=true)]
    [Key()]
    [RoundtripOriginal()]
    public int ID
    {
        get
        {
            return this._id;
        }
        set
        {
            if ((this._id != value))
            {
                this.OnIDChanging(value);
                this.ValidateProperty("ID", value);
                this._id = value;
                this.RaisePropertyChanged("ID");
                this.OnIDChanged();
            }
        }
    }   

まとめ

RIA ServiceはLOBアプリのプラットフォームで簡単に利用できました。一度実践で使ってみたいと思っています。