• SilverLight系列——动态装载XAP包


          其实关于动态装载XAP包,网上已有不少资料,且都附有代码,我当初也是参考网上找到的代码改的,基本原理就是通过WebClient请求XAP文件流,然后分析流,加载程序集,最后通过反射创建实例。细节方面,直接看代码就可以很清楚了:

       /// <summary>
        /// XAP包加载器
       /// </summary>
        public class XapLoader
        {
            /// <summary>
            /// XAP包路径
          /// </summary>
            private string _xapUri;
    
            public XapLoader(string xapUri)
            {
                _xapUri = xapUri;
            }
    
            /// <summary>
            /// 加载元素完毕时触发此事件
          /// </summary>
            public event EventHandler<XapLoadEventArgs> LoadCompleted;
    
            /// <summary>
            /// 从XAP包中加载指定的Xaml文件并实例化为FrameworkElement
            /// </summary>
            /// <param name="xamlFileName">Xaml文件路径</param>
            public void LoadXaml(string xamlFileName)
            {
                Uri uri = new Uri(_xapUri, UriKind.Relative);
    
                WebClient client = new WebClient();
                client.OpenReadCompleted += (sender, e) =>
                {
    
                    StreamResourceInfo resource = Application.GetResourceStream(
                        new StreamResourceInfo(e.Result, null),
                        new Uri(xamlFileName, UriKind.Relative));
    
                    string resourceMainfest = new StreamReader(resource.Stream).ReadToEnd();
                    FrameworkElement element = null;
                    string errorMessage = null;
    
                    try
                    {
                        element = XamlReader.Load(resourceMainfest) as FrameworkElement;
                    }
                    catch (Exception ex)
                    {
                        errorMessage = ex.Message;
                    }
    
                    if (LoadCompleted != null)
                        LoadCompleted(this, new XapLoadEventArgs(element, errorMessage));
                };
    
                client.OpenReadAsync(uri);
            }
    
            /// <summary>
            /// 从XAP包中的指定程序集中加载指定的类型
          /// </summary>
            /// <param name="assmblyName">程序集名称(含后缀)</param>
            /// <param name="typeName">加载类型的完全限定名</param>
            public void LoadControl(string assmblyName, string typeName)
            {
                Uri uri = new Uri(_xapUri, UriKind.Relative);
    
                WebClient client = new WebClient();
                client.OpenReadCompleted += (sender, e) => {
    
                    if (e.Error != null)
                    {
                        if (LoadCompleted != null)
                            LoadCompleted(this, new XapLoadEventArgs(null, e.Error.Message));
                        return;
                    }
    
                    StreamResourceInfo resource = Application.GetResourceStream(
                        new StreamResourceInfo(e.Result, null),
                        new Uri("AppManifest.xaml", UriKind.Relative));
    
                    string resourceMainfest = new StreamReader(resource.Stream).ReadToEnd();
                    var asmPartEls = XDocument.Parse(resourceMainfest).Root.Elements().Elements();
    
                    Assembly assembly = null;
                    foreach (XElement asmPartEl in asmPartEls)
                    {
                        string source = asmPartEl.Attribute("Source").Value;
    
                        if (string.Compare(source,assmblyName, StringComparison.InvariantCultureIgnoreCase)==0)
                        {
                            StreamResourceInfo streamInfo = Application.GetResourceStream(
                                new StreamResourceInfo(e.Result, "application/binary"),
                                new Uri(source, UriKind.Relative));
                            AssemblyPart assemblyPart = new AssemblyPart();
                            assembly = (new AssemblyPart()).Load(streamInfo.Stream);
                        }
                    }
    
                    if (assembly == null)
                    {
                        if (LoadCompleted != null)
                            LoadCompleted(this, new XapLoadEventArgs(null, "未能找到指定程序集!"));
                    }
                    else
                    {
                        FrameworkElement element = null;
                        string errorMessage = null;
    
                        try
                        {
                            Type type = assembly.GetType(typeName);
                            element = Activator.CreateInstance(type) as FrameworkElement;
                        }
                        catch (Exception ex)
                        {
                            errorMessage = ex.Message;
                        }
    
                        if (LoadCompleted != null)
                            LoadCompleted(this, new XapLoadEventArgs(element, errorMessage));
                    }
                };
    
                client.OpenReadAsync(uri);
            }
        }
        /// <summary>
        /// 加载XAP包事件参数
        /// </summary>
        public class XapLoadEventArgs : EventArgs
        {
            private XapLoadEventArgs() { }
    
            public XapLoadEventArgs(FrameworkElement element, string error)
            {
                _element = element;
                _error = error;
            }
    
            private string _error;
            /// <summary>
            /// 获取加载时包含的错误信息
            /// </summary>
            public string Error
            {
                get { return _error; }
            }
    
            private FrameworkElement _element;
            /// <summary>
            /// 获取加载的UI元素
            /// </summary>
            public FrameworkElement Element
            {
                get { return _element; }
            }
        }

          使用方法:

        XapLoader loader = new XapLoader(xapfile);
        loader.LoadCompleted += new EventHandler<XapLoadEventArgs>(loader_LoadCompleted);
        loader.LoadControl(assembly, pageclass);
        然后在loader_LoadCompleted里通过事件参数的Element属性获取加载的UI实例即可。
     

    最后有很重要的一点要提醒:

    比如有SL主程序APP,其中引用了程序集A.DLL,动态加载的XAP包中也包含了程序集A.DLL,但是版本与主程序中引用的不一致,那么
    从XAP包中实例化的对象也将尝试使用主程序APP中所加载的A.DLL,而非XAP包中的A.DLL。所以,这种情况下如果提示“×××方法不存在”,就不要再纳闷了。
  • 相关阅读:
    vant toast 样式引入
    Error: Can‘t resolve ‘swiper/css/swiper.css‘ 解决方案
    Vue中使用provide/inject实现页面reload的方法
    vue 中 关于路径 @ 以及 ~的意义
    ValidationError: Invalid options object. Stylus Loader has been initialized using an options object that does not match the API schema.
    vue 去除链接后的#
    centos7安装elk
    Flask+Celery 异步任务
    centos7用zimg搭建图片存储服务器
    centos7部署nginx与vue搭配及403排错
  • 原文地址:https://www.cnblogs.com/sdlfx/p/2138492.html
Copyright © 2020-2023  润新知