• 利用Async CTP改造Live SDK for WP7


        最近在开发Windows Phone8应用中用到了Live SDK for WP8,但是在将该应用的WP8版本移植到WP7的时候却发生了许多问题,无法直接将项目进行移植。具体原因是因为Live SDK for WP8利用了Async特性,但是WP7默认是不支持Async特性的,所以微软在Live SDK  for WP7中还是采用回调函数的方式,这就给代码的移植造成了很大的困难,当时我在想是否要重写一遍后台代码,虽然这个方案可行,但是以后2套代码进行维护的时候,又极度麻烦,我最后还是决定扩展Live SDK for WP7来实现Async特性。

       首先必须下载Async CTP可以参考Windows Phone开发经验谈(16)-使用Async CTP简化异步编程,准备工作做完了,我们就可以开工了

       建立类EAPCommon和AsyncExtensions用于对Live SDK原始方法的扩展

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ExpressWP.Extensions
    {
        internal static class EAPCommon
        {
            internal static void HandleProgress<T, E>(TaskCompletionSource<T> tcs, ProgressChangedEventArgs eventArgs, Func<E> getProgress, IProgress<E> callback)
            {
                if (eventArgs.UserState == tcs)
                {
                    callback.Report(getProgress.Invoke());
                }
            }
            internal static void HandleCompletion<T>(TaskCompletionSource<T> tcs, bool requireMatch, AsyncCompletedEventArgs e, Func<T> getResult, Action unregisterHandler)
            {
                if (requireMatch)
                {
                    if (e.UserState != tcs)
                    {
                        return;
                    }
                }
                try
                {
                    unregisterHandler.Invoke();
                }
                finally
                {
                    if (e.Cancelled)
                    {
                        tcs.TrySetCanceled();
                    }
                    else
                    {
                        if (e.Error != null)
                        {
                            tcs.TrySetException(e.Error);
                        }
                        else
                        {
                            tcs.TrySetResult(getResult.Invoke());
                        }
                    }
                }
            }
        }
    }

      

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Live;
    using ExpressWP.Util;
    
    namespace ExpressWP.Extensions
    {
        public static class AsyncExtensions
        {
            private static Uri GetUri(this WebClient webClient, string path)
            {
                string baseAddress = webClient.BaseAddress;
                Uri address;
                if (!string.IsNullOrEmpty(baseAddress))
                {
                    if (!Uri.TryCreate(new Uri(baseAddress), path, out address))
                    {
                        return webClient.GetUri(Path.GetFullPath(path));
                    }
                }
                else
                {
                    if (!Uri.TryCreate(path, UriKind.Absolute, out address))
                    {
                        return webClient.GetUri(Path.GetFullPath(path));
                    }
                }
                return webClient.GetUri(address);
            }
            private static Uri GetUri(this WebClient webClient, Uri address)
            {
                if (address == null)
                {
                    throw new ArgumentNullException("address");
                }
                Uri result = address;
                if (!address.IsAbsoluteUri && !string.IsNullOrEmpty(webClient.BaseAddress) &&
                    !Uri.TryCreate(new Uri(webClient.BaseAddress), address, out result))
                {
                    return address;
                }
                return result;
            }
    
            public static Task<Stream> OpenReadTaskAsync(this WebClient webClient, string address)
            {
                return webClient.OpenReadTaskAsync(webClient.GetUri(address));
            }
            public static Task<Stream> OpenReadTaskAsync(this WebClient webClient, Uri address)
            {
                TaskCompletionSource<Stream> tcs = new TaskCompletionSource<Stream>(address);
                OpenReadCompletedEventHandler handler = null;
                handler = delegate(object sender, OpenReadCompletedEventArgs e)
                {
                    EAPCommon.HandleCompletion<Stream>(tcs, true, e, () => e.Result, delegate
                    {
                        webClient.OpenReadCompleted -= (handler);
                    });
                };
                webClient.OpenReadCompleted += (handler);
                try
                {
                    webClient.OpenReadAsync(address, tcs);
                }
                catch
                {
                    webClient.OpenReadCompleted -= (handler);
                    throw;
                }
                return tcs.Task;
            }
    
    
    
            public static Task<LoginCompletedEventArgs> LoginTaskAsync(this LiveAuthClient liveAuthClient,
                IEnumerable<string> scopes)
            {
                TaskCompletionSource<LoginCompletedEventArgs> tcs = new TaskCompletionSource<LoginCompletedEventArgs>(scopes);
                EventHandler<LoginCompletedEventArgs> handler = null;
                handler = delegate(object sender, LoginCompletedEventArgs e)
                    {
                        EAPCommon.HandleCompletion<LoginCompletedEventArgs>(tcs, true, e, () => e, delegate
                        {
                            liveAuthClient.LoginCompleted -= (handler);
                        });
                    };
                liveAuthClient.LoginCompleted += (handler);
                try
                {
                    liveAuthClient.LoginAsync(scopes, tcs);
                }
                catch
                {
                    liveAuthClient.LoginCompleted -= (handler);
                    throw;
                }
                return tcs.Task;
            }
    
    
            public static Task<LiveOperationCompletedEventArgs> GetTaskAsync(this LiveConnectClient liveConnectClient,
        string path)
            {
                TaskCompletionSource<LiveOperationCompletedEventArgs> tcs = new TaskCompletionSource<LiveOperationCompletedEventArgs>(path);
                EventHandler<LiveOperationCompletedEventArgs> handler = null;
                handler = delegate(object sender, LiveOperationCompletedEventArgs e)
                {
                    EAPCommon.HandleCompletion<LiveOperationCompletedEventArgs>(tcs, true, e, () => e, delegate
                    {
                        liveConnectClient.GetCompleted -= (handler);
                    });
                };
                liveConnectClient.GetCompleted += (handler);
                try
                {
                    liveConnectClient.GetAsync(path, tcs);
                }
                catch
                {
                    liveConnectClient.GetCompleted -= (handler);
                    throw;
                }
                return tcs.Task;
            }
    
            public static Task<LiveOperationCompletedEventArgs> PostTaskAsync(this LiveConnectClient liveConnectClient,
      string path, IDictionary<string, object> body)
            {
                TaskCompletionSource<LiveOperationCompletedEventArgs> tcs = new TaskCompletionSource<LiveOperationCompletedEventArgs>(path);
                EventHandler<LiveOperationCompletedEventArgs> handler = null;
                handler = delegate(object sender, LiveOperationCompletedEventArgs e)
                {
                    EAPCommon.HandleCompletion<LiveOperationCompletedEventArgs>(tcs, true, e, () => e, delegate
                    {
                        liveConnectClient.PostCompleted -= (handler);
                    });
                };
                liveConnectClient.PostCompleted += (handler);
                try
                {
                    liveConnectClient.PostAsync(path, body, tcs);
                }
                catch
                {
                    liveConnectClient.PostCompleted -= (handler);
                    throw;
                }
                return tcs.Task;
            }
    
    
            public static Task<LiveOperationCompletedEventArgs> UploadTaskAsync(this LiveConnectClient liveConnectClient,
    string path, Uri uri, OverwriteOption over)
            {
                TaskCompletionSource<LiveOperationCompletedEventArgs> tcs = new TaskCompletionSource<LiveOperationCompletedEventArgs>(path);
                EventHandler<LiveOperationCompletedEventArgs> handler = null;
                handler = delegate(object sender, LiveOperationCompletedEventArgs e)
                {
                    EAPCommon.HandleCompletion<LiveOperationCompletedEventArgs>(tcs, true, e, () => e, delegate
                    {
                        liveConnectClient.UploadCompleted -= (handler);
                    });
                };
                liveConnectClient.UploadCompleted += (handler);
                try
                {
                    var stream = FileOperation.GetStreamFromISF(uri);
                    liveConnectClient.UploadAsync(path, "packages.xml", stream, over, tcs);
                }
                catch(Exception ex)
                {
                    liveConnectClient.UploadCompleted -= (handler);
                    throw;
                }
                return tcs.Task;
            }
    
    
    
            public static Task<LiveDownloadCompletedEventArgs> DownloadTaskAsync(this LiveConnectClient liveConnectClient,
    string path)
            {
                TaskCompletionSource<LiveDownloadCompletedEventArgs> tcs = new TaskCompletionSource<LiveDownloadCompletedEventArgs>(path);
                EventHandler<LiveDownloadCompletedEventArgs> handler = null;
                handler = delegate(object sender, LiveDownloadCompletedEventArgs e)
                {
                    EAPCommon.HandleCompletion<LiveDownloadCompletedEventArgs>(tcs, true, e, () => e, delegate
                    {
                        liveConnectClient.DownloadCompleted -= (handler);
                    });
                };
                liveConnectClient.DownloadCompleted += (handler);
                try
                {
                    liveConnectClient.DownloadAsync(path, tcs);
                }
                catch
                {
                    liveConnectClient.DownloadCompleted -= (handler);
                    throw;
                }
                return tcs.Task;
            }
        }
    }

      其实代码并不复杂,我主要为Live SDK扩展了下面4个方法,让它们实现了Async的特性

    DownloadTaskAsync
    UploadTaskAsync
    GetTaskAsync
    LoginTaskAsync

    最后给大家看看实现后的效果。

    这样就不需要嵌套多个回调函数,改善了编程体验,也不需要再维护2套代码了,好了,就说到这里,欢迎大家留言讨论。

  • 相关阅读:
    SVN+Axure版本管理&协同设计(一)
    postgresql数据库删除时提示回话 sessions using the database
    odoo开发笔记 -- many2one搜索更多增加默认过滤条件
    Docker Ubuntu中安装ping ifconfig命令
    odoo开发笔记 -- div标签代替odoo button写法
    odoo开发笔记 -- 模型字段定义中设置默认值
    linux 清空历史命令
    linux 根据端口查看系统进程
    odoo开发笔记 -- self详解
    odoo开发笔记 -- 传递上下文实现列表视图按照指定条件过滤显示
  • 原文地址:https://www.cnblogs.com/cracker/p/Async_Live_Sdk.html
Copyright © 2020-2023  润新知