2

(怖いコードについての提案が必要)

対応する Web サービス ハンドラーを呼び出すために、すべてのビュー モデルに MVVM と一般化された DataService クラスを組み込むことで、古い Windows Phone アプリ コードに優雅さをもたらそうとしています。

たとえば、通知 ViewModel には次のようなものがあります。

private ObservableCollection<Notification> _notifications;
public ObservableCollection<Notification> Notifications
{
    get
    {
        return _notifications;
    }
}

public void GetNotifications()
{
    new DataService().DownloadViewModelData<ObservableCollection<Notification>>(GetNotificationsCallback, "getnotificationslist.ashx");
    this.IsDataLoaded = true;
}

public void GetNotificationsCallback(ObservableCollection<Notification> notificationsList)
{
    _notifications = notificationsList;
       
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        NotifyPropertyChanged("Notifications");
    });
    this.IsDataLoaded = true;
}

DataService クラスでは、サービスと通信するためのジェネリック メソッドを作成しようとしています。

public static string ServerUrl = "http://<ip-address>:<port>/";

public void DownloadViewModelData<T>(Action<T> callbackFunction, string handlerName, bool methodIsPOST = false, List<KeyValuePair<string, string>> querySet = null) where T : class
{
    var queryString = "";

    if(null != querySet)
    {
        foreach (KeyValuePair<string, string> tuple in querySet)
        {
            queryString += tuple.Key + "=" + tuple.Value + "&";
        }

        queryString = queryString.Remove(queryString.Length - 1, 1);
    }

    var urlQueryString = ServerUrl + handlerName;

    if (!methodIsPOST)
        urlQueryString += queryString;

    var webRequest = HttpWebRequest.CreateHttp(urlQueryString);

    webRequest.ContentType = "application/x-www-form-urlencoded";

    Func<AsyncCallback, object, IAsyncResult> requestingMethod = null;

    if (methodIsPOST)
    {
        webRequest.Method = "POST";
        webRequest.ContentLength = queryString.Length;
        webRequest.BeginGetRequestStream(
            a =>
            {

                System.IO.Stream postStream = webRequest.EndGetRequestStream(a);
                byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(queryString);
                postStream.Write(byteArray, 0, queryString.Length);
                postStream.Close();
                webRequest.BeginGetResponse(
                    b =>
                    {
                        using (WebResponse response = webRequest.EndGetResponse(b))
                        {
                            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                            {
                                callbackFunction(new DataContractJsonSerializer(typeof(T)).ReadObject(response.GetResponseStream()) as T);
                            }
                        }
                    },
                    null
                );
            },
            null
        );
    }
    else
    {
        webRequest.Method = "GET";
        webRequest.BeginGetResponse(
            a =>
            {
                using (WebResponse response = webRequest.EndGetResponse(a))
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        callbackFunction(new DataContractJsonSerializer(typeof(T)).ReadObject(response.GetResponseStream()) as T);
                    }
                }
            },
            null
        );
    }
}



質問:

  1. ラムダ式を使用する正しい (最新の) 方法と、MVVM のデータ層を処理するための全体的な正しいアプローチですか (プロジェクトに複数のモデル、ビュー、およびビューモデルがある場合)?

  2. Portable Class Library (PCL)で Web サービスを呼び出すために、このアプローチをお勧めしますか?

4

1 に答える 1

2

私の意見では、ViewModel がデータ サービスの実装について何も認識しないように、これを行うためのはるかに優れた方法があります。

私がやろうとしていることはいくつかあります。

  1. Ninjectのような依存性注入フレームワークの使用を開始します。これにより、ViewModel が使用しているデータ サービスのタイプを認識しないようにすることができます。DI フレームワークを使用して、コードに特定の実装を挿入できます。
  2. データサービスを表すインターフェースを作成します。議論のために、私の例を と呼びますIDataService。このインターフェイスの主な目的は、データを取得するメソッドを抽象化することです。したがって、データは、データベース、Web サービス、またはファイルからのアクセスであり、viewmodel が何らかの知識 (またはケア) を持っている可能性があります。

あなたのコードには、次の署名を付けます。

public interface IDataService
{
    Task<IEnumerable<Notification>> ListNotifications();
}

Task<>.Net 4.5 非同期フレームワークを利用できるようにするために、私が使用していることに気付くでしょう。これで、I have a way of returning a list of notifications, asynchronously. これは、ビューモデルに必要な情報です。

  1. を再作成しないでくださいObservableCollection<Notification>。コレクションの内容を変更する必要がある場合は、Clear()再設定しますが、コレクション自体を再バインドまたは再作成しないでください。これには、多くのパフォーマンス上の利点もあります。

  2. インターフェイス定義を移植可能なライブラリに配置した場合、特定のプラットフォーム (WP8 と Win8 など) に特定の実装が必要な場合は、ViewModel でインターフェイスを参照するだけなので、非常に少量の変更のみが必要になる場合があります。異なる実装をサポートします。

すべてが理にかなっていることを願っています。

于 2013-02-06T04:12:45.403 に答える