c# - 具有 JSON 反序列化功能的 Windows Phone 8 MVVM

标签 c# windows-phone-8 windows-phone .net-4.5 c#-5.0

(需要有关可怕代码的建议)

我试图通过合并 MVVM 和所有 View 模型的通用 DataService 类来调用其相应的 Web 服务处理程序,从而为我的旧 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. 这是使用 lambda 表达式和整体正确方法来处理 MVVM 数据层的正确(现代)方法吗(假设我们的项目中有多个模型、 View 和 View 模型)?

  2. 您会推荐这种方法来调用Portable Class Library (PCL)中的网络服务吗? ?

最佳答案

在我看来,有一种更好的方法可以做到这一点,这样您的 ViewModel 就不会了解有关数据服务的实现的任何信息。

我会考虑做几件事。

  1. 开始使用依赖注入(inject)框架,如 Ninject 。这将使您的 ViewModel 不知道它正在使用的数据服务的类型。您可以使用 DI 框架为您的代码注入(inject)特定的实现。
  2. 创建一个代表您的数据服务的接口(interface)。为了便于论证,我将我的示例称为 IDataService 。该接口(interface)的主要目标是抽象出检索数据的方法。因此,可以使用具有任何知识(或关心)的 View 模型从数据库、网络服务或文件访问数据。

对于您的代码,我会给它签名:

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

你会注意到我正在使用Task<>这使我能够利用 .Net 4.5 异步框架。现在我们的界面只显示:I have a way of returning a list of notifications, asynchronously 。这就是您的 View 模型需要的信息。

  1. 不要重新创建您的 ObservableCollection<Notification> 。如果需要更改集合的内容,Clear()它,然后重新填充,但不要重新绑定(bind)或重新创建集合本身。这也有许多性能优势。

  2. 如果您将接口(interface)定义放在可移植库中,那么如果您需要特定平台的特定实现(例如 WP8 与 Win8),那么由于您仅在 ViewModel 中引用接口(interface),那么您可能只有更改非常小的数量以支持差异实现。

希望一切都有意义。

关于c# - 具有 JSON 反序列化功能的 Windows Phone 8 MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14719632/

相关文章:

c# - 发送带有命令参数的对象

windows-phone - 适用于 Windows Phone 8.1 的独立资源管理器工具?

c# - IOFileNotFoundException mscorlib.dll

c# - 向 MVCcontrib 网格上的每一行添加复选框

c# - 如何动态找出所有具有自定义属性的方法

c# - 如何在不卸载整个产品的情况下将 Visual Studio 2013 Update 5 恢复到 Visual Studio 2013 Update 4

windows-phone-8 - Visual Studio 2013 中 Windows Phone 项目和 Silverlight Windows Phone 项目的区别

javascript - 添加特定于 Windows Phone Internet Explorer 的代码

c# - 纵向模式下的 Windows Phone map.setView()

c# - 将数据从 Unity 发送到 Raspberry