<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      突破 Silverlight 自身限制, 做更好的動態加載導航機制(二)

      上一篇文章中, 動態導航的思路已經比較完善了, 現在來實現動態導航機制。

      實現按需加載 Silverlight 組件

      Silverlight 客戶端加載一個程序集很容易, 關鍵是如何分析并加載程序集引用的其它程序集, 這些程序集又會引用另外的程序集, 然后再加在這些程序集。

      借助于 Mono.Cecil ,可以在客戶端很容易的分析出程序集引用的其它程序集

      至于如何加載, 我的實現思路是, 做一個下載隊列, 每下載一個程序集, 分析其引用的程序集列表, 找出其沒有加載過的程序集, 添加到下載隊列, 從下載隊列中刪除下載過的程序集, 如果隊列不為空, 則依次進行遞歸; 否則,觸發下載完成事件。實現代如下:

      public class AssemblyDownloader {
      
         private static readonly IDictionary LoadedAssemblies = new Dictionary(StringComparer.OrdinalIgnoreCase);
         private readonly ISet _loadingSet = new HashSet();
         private static readonly object LoadingSetLock = new object();
         
         private static readonly string[] SilverlightRuntimeAssemblyNames = new[] {
            "Microsoft.VisualBasic.dll",
            "mscorlib.dll",
            "System.Core.dll",
            "System.dll",
            "System.Net.dll",
            "System.Runtime.Serialization.dll",
            "System.ServiceModel.dll",
            "System.ServiceModel.Web.dll",
            "System.Windows.Browser.dll",
            "System.Windows.dll",
            "System.Windows.RuntimeHost.dll",
            "System.Xml.dll"
         };
         
         private bool _isbusy;
         private string _loadingAssemblyName;
      
         public event EventHandler DownloadAssemblyCommpleted;
         public event EventHandler DownloadFailed;
      
         public Assembly GetAssembly(string assemblyName) {
            return LoadedAssemblies.ContainsKey(assemblyName) ? LoadedAssemblies[assemblyName] : null;
         }
      
         public void OnDownloadFailed(Exception ex) {
            var handler = this.DownloadFailed;
            if (handler != null) {
               handler(this, new AsyncCompletedEventArgs(ex, true, null));
            }
         }
      
         private void OnDownloadAssemblyCommpleted(DownloadAssemblyCommpletedEventArgs e) {
            var handler = this.DownloadAssemblyCommpleted;
            if (handler != null) {
               handler(this, e);
            }
         }
      
         public void DownloadAssemblyAsync(string assemblyName) {
            if (this._isbusy) {
               throw new InvalidOperationException(string.Format("AssemblyDownloader is loading {0}, please waite ...", this._loadingAssemblyName));
            }
            assemblyName = EnsureEndWdithDll(assemblyName);
            this._loadingAssemblyName = assemblyName;
            if (IsAssemblyLoaded(assemblyName)) {
               this.DownloadCompleted();
            }
            else {
               DownloadAssemblyAsyncCore(assemblyName);
            }
         }
      
         private void DownloadAssemblyAsyncCore(string assemblyName) {
            this._isbusy = true;
            assemblyName = EnsureEndWdithDll(assemblyName);
            var name = assemblyName;
            var webClient = new WebClient();
            webClient.OpenReadCompleted += (sender, e) => this.OnReadOneAssembly(name, e);
            try {
               webClient.OpenReadAsync(new Uri(assemblyName, UriKind.Relative));
            }
            catch (Exception ex) {
               this.OnDownloadFailed(ex);
            }
         }
      
         private static string EnsureEndWdithDll(string assemblyName) {
            if (!assemblyName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) {
               assemblyName += ".dll";
            }
            return assemblyName;
         }
      
         private void OnReadOneAssembly(string name, OpenReadCompletedEventArgs e) {
            if (e.Error != null) {
               this.OnDownloadFailed(e.Error);
               this._isbusy = false;
               return;
            }
            var assemblyStream = e.Result;
            var references = GetReferenceAssemblyNames(assemblyStream);
            AddNotLoadedReferenceAssemblyToLoadingSet(references);
      
            assemblyStream.Seek(0, SeekOrigin.Begin);
            LoadToAssemblyPart(assemblyStream, name);
      
            if (this._loadingSet.Count > 0) {
               var asm = this._loadingSet.First();
               lock (LoadingSetLock) {
                  this._loadingSet.Remove(asm);
               }
               this.DownloadAssemblyAsyncCore(asm);
            }
            else {
               this.DownloadCompleted();
            }
         }
      
         private void DownloadCompleted() {
            this._isbusy = false;
            var assembly = this.GetAssembly(this._loadingAssemblyName);
            this.OnDownloadAssemblyCommpleted(new DownloadAssemblyCommpletedEventArgs(assembly));
         }
      
         private static void LoadToAssemblyPart(Stream assemblyStream, string name) {
            var part = new AssemblyPart {
               Source = name
            };
            var assembly = part.Load(assemblyStream);
            LoadedAssemblies.Add(name, assembly);
         }
      
         private void AddNotLoadedReferenceAssemblyToLoadingSet(IEnumerable references) {
            var referencesNotLoaded = from reference in references
                                      where !(IsAssemblyLoaded(reference))
                                      select reference;
            foreach (var @ref in referencesNotLoaded) {
               lock (LoadingSetLock) {
                  if (!this._loadingSet.Contains(@ref)) {
                     this._loadingSet.Add(@ref);
                  }
               }
            }
         }
      
         private static bool IsAssemblyLoaded(string assemblyName) {
            return SilverlightRuntimeAssemblyNames.Any(asmName => asmName.Equals(assemblyName, StringComparison.OrdinalIgnoreCase))
               || LoadedAssemblies.ContainsKey(assemblyName)
               || Deployment.Current.Parts.Any(ap => ap.Source.Equals(assemblyName, StringComparison.OrdinalIgnoreCase));
         }
      
         private static IEnumerable GetReferenceAssemblyNames(Stream assemblyStream) {
            var asmDef = AssemblyDefinition.ReadAssembly(assemblyStream);
            return asmDef.MainModule.AssemblyReferences.Select(anr => anr.Name + ".dll");
         }
      }

      實現一個自定義的 ContentLoader

      實現自定義的 ContentLoader 很容易, 只要實現 INavigationContentLoader 接口即可, 結合上面的AssemblyDownloader, 實現代碼如下:

      public class MyContentLoader : INavigationContentLoader {
      
         private static AssemblyDownloader _assemblyDownloader;
      
         public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState) {
            var typeFullName = targetUri.ToString();
            if (string.IsNullOrEmpty(typeFullName)) {
               return null;
            }
            var arr = typeFullName.Split(',');
            var typeName = arr[0];
            var assemblyName = arr[1];
            if (!assemblyName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) {
               assemblyName += ".dll";
            }
            var asyncResult = new MyContentLoaderAsyncResult {
               AsyncState = asyncState,
               TypeName = typeName,
               AssemblyName = assemblyName
            };
            BeginLoadCore(userCallback, asyncResult);
            return asyncResult;
         }
      
         private static void BeginLoadCore(AsyncCallback userCallback, MyContentLoaderAsyncResult result) {
            if (_assemblyDownloader == null) {
               _assemblyDownloader = new AssemblyDownloader();
            }
            var handlers = new EventHandler[1];
            handlers[0] = (sender, e) => {
               _assemblyDownloader.DownloadAssemblyCommpleted -= handlers[0];
               result.Assembly = e.Result;
               userCallback(result);
            };
            _assemblyDownloader.DownloadAssemblyCommpleted += handlers[0];
            _assemblyDownloader.DownloadAssemblyAsync(result.AssemblyName);
         }
      
         public void CancelLoad(IAsyncResult asyncResult) {
         }
      
         public LoadResult EndLoad(IAsyncResult asyncResult) {
            var result = asyncResult as MyContentLoaderAsyncResult;
            if (result == null) {
               throw new InvalidOperationException(string.Format("Wrong kind of {0} passed in.  The {0} passed in should only come from {1}.", "IAsyncResult", "MyContentLoader.BeginLoad"));
            }
            var loadResult = new LoadResult(result.GetResultInstance());
            return loadResult;
         }
      
         public bool CanLoad(Uri targetUri, Uri currentUri) {
            return targetUri.ToString().Split(',').Length == 2;
         }
      }

      使用自定義的 ContentLoader

      只要設置 Frame 控件的 ContentLoader 為自定義的 ContentLoader 即可, 比如可以這樣使用:

      
      
      
         
            
         </SDK:FRAME.CONTENTLOADER />
      

      當加載第一個程序集的時候, 會自動加載引用的程序集, 如下圖:

      image

      當加載第二個程序集的時候, 重復引用的程序集將不會被加載, 如下圖:

      image

      與 Silverlight 內置的導航機制比較

      與內置的導航機制相比, 最大的優點是實現了真正的按需加載, 可以有效地減少主程序的大小, 減少用戶的初次等待時間, 而且可以支持 OOB 模式。

      posted @ 2011-08-11 13:32  張志敏  閱讀(934)  評論(10)    收藏  舉報
      主站蜘蛛池模板: 亚洲av成人无码精品电影在线| 四虎女优在线视频免费看| 377P欧洲日本亚洲大胆| 成人网站免费观看永久视频下载| 伊人无码精品久久一区二区| 18女下面流水不遮图| 铁力市| 蚌埠市| 男人和女人高潮做爰视频| 开心一区二区三区激情| 日韩欧美卡一卡二卡新区| 亚洲精品无码久久千人斩| 久久亚洲精品中文字幕无| 国产精品不卡一二三区| 国产午夜91福利一区二区| 精品乱码一区二区三四五区 | 他掀开裙子把舌头伸进去添视频| 久热综合在线亚洲精品| 亚洲电影天堂av2017| 欧美三级中文字幕在线观看| 人妻中文字幕亚洲精品| 国产亚洲av日韩精品熟女 | 免费无码一区无码东京热| 精品偷拍一区二区三区| 高中女无套中出17p| 亚洲嫩模一区二区三区| 蜜桃成人无码区免费视频网站| 精品国产美女av久久久久 | 午夜精品区| 无码一级视频在线| 亚洲精品动漫一区二区三| 漂亮的保姆hd完整版免费韩国| 丁香婷婷激情综合俺也去| 激情综合网激情国产av| 中文字幕在线精品国产| 国产99久久精品一区二区| 被黑人伦流澡到高潮HNP动漫| 99久久精品费精品国产一区二| 中文字幕精品无码一区二区| av无码一区二区大桥久未| 国产成人啪精品午夜网站|