prism框架里module太多启动速度过慢

一个基于prism框架desktop项目,总共有100多个module。程序启动的时候有几秒钟的delay。

用的DirectoryModuleCatalog类从本地目录中装载module的程序集。

附:DirectoryModuleCatalog装载部分源代码

ExpandedBlockStart.gif View Code
// ===================================================================================
//  Microsoft patterns & practices
//  Composite Application Guidance for Windows Presentation Foundation and Silverlight
// ===================================================================================
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
//  OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
//  LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//  FITNESS FOR A PARTICULAR PURPOSE.
// ===================================================================================
//  The example companies, organizations, products, domain names,
//  e-mail addresses, logos, people, places, and events depicted
//  herein are fictitious.  No association with any real company,
//  organization, product, domain name, email address, logo, person,
//  places, or events is intended or should be inferred.
// ===================================================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Policy;
using Microsoft.Practices.Prism.Properties;

namespace Microsoft.Practices.Prism.Modularity
{
     ///   <summary>
    
///  Represets a catalog created from a directory on disk.
    
///   </summary>
    
///   <remarks>
    
///  The directory catalog will scan the contents of a directory, locating classes that implement
    
///   <see cref="IModule"/>  and add them to the catalog based on contents in their associated  <see cref="ModuleAttribute"/> .
    
///  Assemblies are loaded into a new application domain with ReflectionOnlyLoad.  The application domain is destroyed
    
///  once the assemblies have been discovered.
    
///  
    
///  The diretory catalog does not continue to monitor the directory after it has created the initialze catalog.
    
///   </remarks>
     public  class DirectoryModuleCatalog : ModuleCatalog
    {
         ///   <summary>
        
///  Directory containing modules to search for.
        
///   </summary>
         public  string ModulePath {  getset; }

         ///   <summary>
        
///  Drives the main logic of building the child domain and searching for the assemblies.
        
///   </summary>
         protected  override  void InnerLoad()
        {
             if ( string.IsNullOrEmpty( this.ModulePath))
                 throw  new InvalidOperationException(Resources.ModulePathCannotBeNullOrEmpty);

             if (!Directory.Exists( this.ModulePath))
                 throw  new InvalidOperationException(
                     string.Format(CultureInfo.CurrentCulture, Resources.DirectoryNotFound,  this.ModulePath));

            AppDomain childDomain =  this.BuildChildDomain(AppDomain.CurrentDomain);

             try
            {
                List< string> loadedAssemblies =  new List< string>();

                 var assemblies = (
                                      from Assembly assembly  in AppDomain.CurrentDomain.GetAssemblies()
                                      where !(assembly  is System.Reflection.Emit.AssemblyBuilder)
                                        && assembly.GetType().FullName !=  " System.Reflection.Emit.InternalAssemblyBuilder "
                                        && !String.IsNullOrEmpty(assembly.Location)
                                      select assembly.Location
                                 );

                loadedAssemblies.AddRange(assemblies);

                Type loaderType =  typeof(InnerModuleInfoLoader);

                 if (loaderType.Assembly !=  null)
                {
                     var loader =
                        (InnerModuleInfoLoader)
                        childDomain.CreateInstanceFrom(loaderType.Assembly.Location, loaderType.FullName).Unwrap();
                    loader.LoadAssemblies(loadedAssemblies);
                     this.Items.AddRange(loader.GetModuleInfos( this.ModulePath));
                }
            }
             finally
            {
                AppDomain.Unload(childDomain);
            }
        }


         ///   <summary>
        
///  Creates a new child domain and copies the evidence from a parent domain.
        
///   </summary>
        
///   <param name="parentDomain"> The parent domain. </param>
        
///   <returns> The new child domain. </returns>
        
///   <remarks>
        
///  Grabs the  <paramref name="parentDomain"/>  evidence and uses it to construct the new
        
///   <see cref="AppDomain"/>  because in a ClickOnce execution environment, creating an
        
///   <see cref="AppDomain"/>  will by default pick up the partial trust environment of 
        
///  the AppLaunch.exe, which was the root executable. The AppLaunch.exe does a 
        
///  create domain and applies the evidence from the ClickOnce manifests to 
        
///  create the domain that the application is actually executing in. This will 
        
///  need to be Full Trust for Composite Application Library applications.
        
///   </remarks>
        
///   <exception cref="ArgumentNullException"> An  <see cref="ArgumentNullException"/>  is thrown if  <paramref name="parentDomain"/>  is null. </exception>
         protected  virtual AppDomain BuildChildDomain(AppDomain parentDomain)
        {
             if (parentDomain ==  nullthrow  new System.ArgumentNullException( " parentDomain ");

            Evidence evidence =  new Evidence(parentDomain.Evidence);
            AppDomainSetup setup = parentDomain.SetupInformation;
             return AppDomain.CreateDomain( " DiscoveryRegion ", evidence, setup);
        }

         private  class InnerModuleInfoLoader : MarshalByRefObject
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage( " Microsoft.Performance "" CA1822:MarkMembersAsStatic ")]
             internal ModuleInfo[] GetModuleInfos( string path)
            {
                DirectoryInfo directory =  new DirectoryInfo(path);

                ResolveEventHandler resolveEventHandler =
                     delegate( object sender, ResolveEventArgs args) {  return OnReflectionOnlyResolve(args, directory); };

                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += resolveEventHandler;

                Assembly moduleReflectionOnlyAssembly =
                    AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().First(
                        asm => asm.FullName ==  typeof(IModule).Assembly.FullName);
                Type IModuleType = moduleReflectionOnlyAssembly.GetType( typeof(IModule).FullName);

                IEnumerable<ModuleInfo> modules = GetNotAllreadyLoadedModuleInfos(directory, IModuleType);

                 var array = modules.ToArray();
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= resolveEventHandler;
                 return array;
            }

             private  static IEnumerable<ModuleInfo> GetNotAllreadyLoadedModuleInfos(DirectoryInfo directory, Type IModuleType)
            {
                List<FileInfo> validAssemblies =  new List<FileInfo>();
                Assembly[] alreadyLoadedAssemblies = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();

                 var fileInfos = directory.GetFiles( " *.dll ")
                    .Where(file => alreadyLoadedAssemblies
                                       .FirstOrDefault(
                                       assembly =>
                                       String.Compare(Path.GetFileName(assembly.Location), file.Name,
                                                      StringComparison.OrdinalIgnoreCase) ==  0) ==  null);
                
                 foreach (FileInfo fileInfo  in fileInfos)
                {
                    Assembly assembly =  null;
                     try
                    {
                        assembly = Assembly.ReflectionOnlyLoadFrom(fileInfo.FullName);
                        validAssemblies.Add(fileInfo);
                    }
                     catch (BadImageFormatException)
                    {
                         //  skip non-.NET Dlls
                    }
                }

                 return validAssemblies.SelectMany(file => Assembly.ReflectionOnlyLoadFrom(file.FullName)
                                            .GetExportedTypes()
                                            .Where(IModuleType.IsAssignableFrom)
                                            .Where(t => t != IModuleType)
                                            .Where(t => !t.IsAbstract)
                                            .Select(type => CreateModuleInfo(type)));
            }

             private  static Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
            {
                Assembly loadedAssembly = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies().FirstOrDefault(
                    asm =>  string.Equals(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase));
                 if (loadedAssembly !=  null)
                {
                     return loadedAssembly;
                }
                AssemblyName assemblyName =  new AssemblyName(args.Name);
                 string dependentAssemblyFilename = Path.Combine(directory.FullName, assemblyName.Name +  " .dll ");
                 if (File.Exists(dependentAssemblyFilename))
                {
                     return Assembly.ReflectionOnlyLoadFrom(dependentAssemblyFilename);
                }
                 return Assembly.ReflectionOnlyLoad(args.Name);
            }

            [System.Diagnostics.CodeAnalysis.SuppressMessage( " Microsoft.Performance "" CA1822:MarkMembersAsStatic ")]
             internal  void LoadAssemblies(IEnumerable< string> assemblies)
            {
                 foreach ( string assemblyPath  in assemblies)
                {
                     try
                    {
                        Assembly.ReflectionOnlyLoadFrom(assemblyPath);
                    }
                     catch (FileNotFoundException)
                    {
                         //  Continue loading assemblies even if an assembly can not be loaded in the new AppDomain
                    }
                }
            }

             private  static ModuleInfo CreateModuleInfo(Type type)
            {
                 string moduleName = type.Name;
                List< string> dependsOn =  new List< string>();
                 bool onDemand =  false;
                 var moduleAttribute =
                    CustomAttributeData.GetCustomAttributes(type).FirstOrDefault(
                        cad => cad.Constructor.DeclaringType.FullName ==  typeof(ModuleAttribute).FullName);

                 if (moduleAttribute !=  null)
                {
                     foreach (CustomAttributeNamedArgument argument  in moduleAttribute.NamedArguments)
                    {
                         string argumentName = argument.MemberInfo.Name;
                         switch (argumentName)
                        {
                             case  " ModuleName ":
                                moduleName = ( string) argument.TypedValue.Value;
                                 break;

                             case  " OnDemand ":
                                onDemand = ( bool) argument.TypedValue.Value;
                                 break;

                             case  " StartupLoaded ":
                                onDemand = !(( bool) argument.TypedValue.Value);
                                 break;
                        }                           
                    }
                }

                 var moduleDependencyAttributes =
                    CustomAttributeData.GetCustomAttributes(type).Where(
                        cad => cad.Constructor.DeclaringType.FullName ==  typeof(ModuleDependencyAttribute).FullName);

                 foreach (CustomAttributeData cad  in moduleDependencyAttributes)
                {
                    dependsOn.Add(( string) cad.ConstructorArguments[ 0].Value);
                }

                ModuleInfo moduleInfo =  new ModuleInfo(moduleName, type.AssemblyQualifiedName)
                                            {
                                                InitializationMode =
                                                    onDemand
                                                        ? InitializationMode.OnDemand
                                                        : InitializationMode.WhenAvailable,
                                                Ref = type.Assembly.CodeBase,
                                            };
                moduleInfo.DependsOn.AddRange(dependsOn);
                 return moduleInfo;
            }
        }
    }
}

 

初步怀疑是在这里花费了太多的时间。

解决方式:

准备使用xaml文件来存储modules的配置信息。第一次启动程序当模块装载成功以后,创建一个xaml配置文件。

以后启动程序不再遍历目录,之间从xaml文件读取配置信息。

 

代码如下:

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Prism.Modularity;
using System.IO;

namespace ModularityWithUnity.Desktop
{
     public  class ModuleCatalogConfigXAML
    {
         private  const  string SPACE_STRING_4 =  "      ";
         private  const  string SPACE_STRING_8 =  "          ";
         private ModuleCatalog moduleCatalog;
         private StringBuilder sb;

         public ModuleCatalogConfigXAML(ModuleCatalog moduleCatalog)
        {
            sb =  new StringBuilder();
             this.moduleCatalog = moduleCatalog;
        }

         public  void GenerateXAMLConfigFile( string fileFullPath)
        {
            BuildHeader();
            BuildGroups();
            BuildByGroupless();
            BuildFooter();
            SaveAsFile(fileFullPath, sb.ToString());
        }

         private  static  void SaveAsFile( string savedPath,  string content)
        {
            
             using (StreamWriter sw = File.CreateText(savedPath))
            {
                sw.Write(content);
            }
        }

         private  void BuildHeader()
        {
            sb.AppendLine( " <Modularity:ModuleCatalog xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" ");
            sb.AppendLine(SPACE_STRING_8 + " xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" ");
            sb.AppendLine(SPACE_STRING_8 +  " xmlns:sys=\"clr-namespace:System;assembly=mscorlib\" ");
            sb.AppendLine(SPACE_STRING_8 +  " xmlns:Modularity=\"clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism\"> ");

        }

         private  void BuildFooter()
        {
            sb.AppendLine( " </Modularity:ModuleCatalog> ");
        }

         private  void BuildGroups()
        {
             foreach ( var group  in moduleCatalog.Groups)
            {
                BuildByGroup(group);
            }
        }

         private  void BuildByGroup(ModuleInfoGroup group)
        {
             // IEnumerable<ModuleInfoGroup> groups = this.moduleCatalog.Groups;
            sb.AppendLine(SPACE_STRING_4 +  " <Modularity:ModuleInfoGroup  ");
             if (! string.IsNullOrEmpty(group.Ref))
            {
                sb.Append( "  Ref=\" " + group.Ref +  " \" ");
            }

            sb.Append( "  InitializationMode=\" " + group.InitializationMode.ToString() + " \"> ");
            IEnumerator<ModuleInfo> moduleInfos = group.GetEnumerator();
            
             while(moduleInfos.MoveNext())
            {
                BuildModule(moduleInfos.Current,SPACE_STRING_8);
            }
        }

         private  void BuildByGroupless()
        {
            IEnumerable<ModuleInfo> groupLessModules =  this.moduleCatalog.Items.OfType<ModuleInfo>();
             foreach ( var moduleInfo  in groupLessModules)
            {
                BuildModule( moduleInfo,SPACE_STRING_4);
            }
        }

         private  void BuildModule(ModuleInfo moduleInfo, string space)
        {
            sb.AppendLine(space +  " <!-- Module info without a group --> ");

             string content = space +  " <Modularity:ModuleInfo  ";

            
             if (! string.IsNullOrEmpty(moduleInfo.Ref))
            {
                content +=  "  Ref=\" " + moduleInfo.Ref +  " \" ";
            }

             if (! string.IsNullOrEmpty(moduleInfo.ModuleName))
            {
                content +=  "  ModuleName=\" " + moduleInfo.ModuleName +  " \" ";
            }

            content +=  "  ModuleType=\" " + moduleInfo.ModuleType +  " \" > ";

            sb.AppendLine(content);

             if (moduleInfo.DependsOn !=  null && moduleInfo.DependsOn.Count> 0)
            {
                sb.AppendLine(space + SPACE_STRING_4 +  " <Modularity:ModuleInfo.DependsOn> ");
                 foreach ( var item  in moduleInfo.DependsOn)
                {
                    sb.AppendLine(space + SPACE_STRING_4 + SPACE_STRING_4 +  " <sys:String> " + item +  " </sys:String> ");
                }

                sb.AppendLine(space + SPACE_STRING_4 +  " </Modularity:ModuleInfo.DependsOn> ");
                sb.AppendLine(space +  " </Modularity:ModuleInfo>  ");
            }
           
            sb.AppendLine(space +  " </Modularity:ModuleInfo>  ");
                 // sb.Append(" />");
            
        }
    }
}

 

使用的时候:

UnityBootstrapper

 

 1.虚方法CreateModuleCatalog 用来返回ModuleCatalog类。
  在此方法中添加逻辑如下:
如果modules的配置文件已经存在,则通过配置文件来生成ModuleCatalog.
2.虚方法InitializeModules装载模块信息,在此方法后调用GenerateXAMLConfigFile 生成模块配置文件。
 

 

转载于:https://www.cnblogs.com/umlchina/archive/2011/11/21/2257205.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WPF Prism框架是一个面向对象的框架,用于开发模块化、可扩展的WPF应用程序,它基于MVVM设计模式和依赖注入技术。该框架的主要目的是能够轻松地实现可插拔的模块,公共的服务、组件和工具类的共享,同时也提供了灵活的路由、事件聚合、模块加载、导航和命令处理等机制。使用WPF Prism框架可以快速地开发出灵活的WPF应用程序,从而提高代码质量和开发效率,减少代码的维护难度。 WPF Prism框架具有以下的特点: 1. 扩展性:可以轻松地添加新的模块、服务和组件,同时也可以快速替换现有的组件。 2. 可重用性:提供了丰富的公共组件、服务和工具类,从而可以提高代码的可重用性。 3. 灵活性:提供了灵活的路由、事件聚合、模块加载和导航等机制,能够更好地满足应用程序的需求。 4. 易用性:提供了一套完整的MVVM设计模式和依赖注入技术的实践方案,从而能够更好地组织应用程序的逻辑。 总之,WPF Prism框架是一个强大的工具,能够让我们更好地开发WPF应用程序,提高代码质量和开发效率,实现可插拔的模块化和可扩展性,同时也具有灵活性和易用性。 ### 回答2: WPF Prism框架是一种面向MVVM模式的开源框架,它帮助开发人员使用模块化的方式构建可扩展、可重用和易于维护的WPF应用程序。该框架主要由Microsoft和模式仲裁者团队开发和维护,它借鉴了许多现代的软件开发理念,比如IoC容器、依赖注入和事件聚合器等。 WPF Prism框架的核心思想是将应用程序分解为许多可独立维护和扩展的模块。这些模块可以基于业务逻辑、UI、数据或任何其他特征进行分组。在该框架中,模块由各种名为“组件”的构建块组成。这些组件包括视图(View)、视图模型(ViewModel)、服务(Service)、模型(Model)等。通过基于这些组件的开发,可以实现具有高度可伸缩性和可重用性的应用程序。 为了实现这种模块化开发和组件化架构,WPF Prism框架提供了一些重要的工具和特性。例如,在该框架中可以使用依赖注入容器(如Unity)来管理组件及其依赖关系。此外,该框架还提供了一些基于事件的消息机制,可方便地实现模块间的交互和通信。 总体来说,WPF Prism框架是一种利用开源技术实现企业级应用程序开发的最佳选择。它具有良好的模块化、组件化和可扩展性特性,可以在实现复杂WPF应用程序时提高开发效率和代码质量。 ### 回答3: WPF Prism是一个基于WPF的框架,它为大型应用程序提供了一种组织、设计和部署的方式。它旨在帮助开发者构建可扩展、可维护和可测试的WPF应用程序。 WPF Prism采用了面向模块的编程思想,它将整个应用程序划分为多个模块,每个模块都包含自己的逻辑和用户界面。这种模块化设计使得应用程序易于扩展和维护,同时也简化了开发流程。 WPF Prism同时提供了一组强大的工具和功能,如依赖注入、命令模式和事件聚合等,这些功能让WPF应用程序更加易于开发和测试。它还提供了一个强大的导航和区域管理系统,开发者可以使用这些系统来管理不同部分的用户界面和功能。 总之,WPF Prism是一个优秀的框架,它为开发者提供了全面的工具和功能,使得构建WPF应用程序变得更加容易和高效。它的结构良好、可扩展性强,而且可以充分利用WPF的强大功能。无论是大型企业应用程序还是小型桌面应用程序,WPF Prism都是一个理想的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值