zoukankan      html  css  js  c++  java
  • 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。所以,这种情况下如果提示“×××方法不存在”,就不要再纳闷了。
  • 相关阅读:
    The Quad
    将OrCAD Capture CIS的设计文件(.dsn)导入到PADS Logic VX.2.3
    OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件
    Eclipse IDE 添加jar包到Java工程中
    PADS Logic VX.2.3 修改软件界面语言
    切换Allegro PCB Editor
    Allegro PCB Design GXL (legacy) 将brd文件另存为低版本文件
    Allegro PCB Design GXL (legacy) 设置自动保存brd文件
    Could not create an acl object: Role '16'
    windows 下apache开启FastCGI
  • 原文地址:https://www.cnblogs.com/sdlfx/p/2138492.html
Copyright © 2011-2022 走看看