Prism学习日记04 module的使用流程

Module的使用流程

在这里插入图片描述
如上图所示,使用模块之前需要:注册模块》发现模块》加载模块》初始化模块

  1. 注册/发现模块:在运行时为特定应用程序加载模块,对应的目录包含要加载的模块,其位置以及加载顺序的信息。
  2. 加载模块:模块的程序集被加载到内存中,需要从某个远程位置或本地目录检索模块。
  3. 初始化模块:创建模块类的实例并通过IModule接口调用它们的Initialize方法。

几个重要的接口介绍

IModuleInfo接口

在这里插入图片描述
可以看到这个接口包含了一些关于module的基本信息,比如:

  1. 依赖项:可以获取被依赖的模块名称
  2. 初始化模式:可以设置或获取初始化的模式,如下
    在这里插入图片描述
  3. 名称:类型:都是对当前module的信息描述
  4. Ref:可以理解为加载路径
  5. 状态,当前module的状态信息,比如:在这里插入图片描述

IModuleCatalog接口

之前也简单提到这个接口,可以理解为module的目录,从源码看就是维护了一个IModuleInfo的集合
在这里插入图片描述
这里比较重要的就是初始化函数,可以先从ModuleCatalogBase类看到,所谓初始化最终是调用了load函数实现,加载module,可以从三个方式进行加载,这里按照 prism学习日记3中的顺序详细补充。

  1. 通过通过动态解析xaml文件进行动态加载
    注意学习日记3中的方法一通过直接添加module达到静态加载目的,和本次的方法略有不同,此处是直接通过解析xaml文件达到动态加载的目的,无需添加模块引用。xaml示例如下:
    在这里插入图片描述
    只需要在重写的加载模块中读取该xaml即可:
    在这里插入图片描述
    这里贴一下源码
 /// <summary>
    /// A catalog built from a XAML file.
    /// </summary>
    public class XamlModuleCatalog : ModuleCatalog
    {
        private readonly Uri _resourceUri;

        private const string _refFilePrefix = "file://";
        private int _refFilePrefixLength = _refFilePrefix.Length;

        /// <summary>
        /// Creates an instance of a XamlResourceCatalog.
        /// </summary>
        /// <param name="fileName">The name of the XAML file</param>
        public XamlModuleCatalog(string fileName)
            : this(new Uri(fileName, UriKind.Relative))
        {
        }

        /// <summary>
        /// Creates an instance of a XamlResourceCatalog.
        /// </summary>
        /// <param name="resourceUri">The pack url of the XAML file resource</param>
        public XamlModuleCatalog(Uri resourceUri)
        {
            _resourceUri = resourceUri;
        }

        /// <summary>
        /// Loads the catalog from the XAML file.
        /// </summary>
        protected override void InnerLoad()
        {
            var catalog = CreateFromXaml(_resourceUri);

            foreach (IModuleCatalogItem item in catalog.Items)
            {
                if (item is ModuleInfo mi)
                {
                    if (!string.IsNullOrWhiteSpace(mi.Ref))
                        mi.Ref = GetFileAbsoluteUri(mi.Ref);
                }
                else if (item is ModuleInfoGroup mg)
                {
                    if (!string.IsNullOrWhiteSpace(mg.Ref))
                    {
                        mg.Ref = GetFileAbsoluteUri(mg.Ref);
                        mg.UpdateModulesRef();
                    }
                    else
                    {
                        foreach (var module in mg)
                        {
                            module.Ref = GetFileAbsoluteUri(module.Ref);
                        }
                    }
                }

                Items.Add(item);
            }
        }

        /// <inheritdoc />
        protected override string GetFileAbsoluteUri(string path)
        {
            //this is to maintain backwards compatibility with the old file:/// and file:// syntax for Xaml module catalog Ref property
            if (path.StartsWith(_refFilePrefix + "/", StringComparison.Ordinal))
            {
                path = path.Substring(_refFilePrefixLength + 1);
            }
            else if (path.StartsWith(_refFilePrefix, StringComparison.Ordinal))
            {
                path = path.Substring(_refFilePrefixLength);
            }

            return base.GetFileAbsoluteUri(path);
        }

        /// <summary>
        /// Creates a <see cref="ModuleCatalog"/> from XAML.
        /// </summary>
        /// <param name="xamlStream"><see cref="Stream"/> that contains the XAML declaration of the catalog.</param>
        /// <returns>An instance of <see cref="ModuleCatalog"/> built from the XAML.</returns>
        private static ModuleCatalog CreateFromXaml(Stream xamlStream)
        {
            if (xamlStream == null)
            {
                throw new ArgumentNullException(nameof(xamlStream));
            }

            return XamlReader.Load(xamlStream) as ModuleCatalog;
        }

        /// <summary>
        /// Creates a <see cref="ModuleCatalog"/> from a XAML included as an Application Resource.
        /// </summary>
        /// <param name="builderResourceUri">Relative <see cref="Uri"/> that identifies the XAML included as an Application Resource.</param>
        /// <returns>An instance of <see cref="ModuleCatalog"/> build from the XAML.</returns>
        private static ModuleCatalog CreateFromXaml(Uri builderResourceUri)
        {
            var streamInfo = System.Windows.Application.GetResourceStream(builderResourceUri);

            if ((streamInfo != null) && (streamInfo.Stream != null))
            {
                return CreateFromXaml(streamInfo.Stream);
            }

            return null;
        }
    }

  1. 通过文件夹路径加载
    同 prism学习日记3中的描述
  2. 通过配置文件加载
    通过一个ConfigurationStore来逐一解析Configuration下面的modules节点并逐一添加到父类中维护的Modules集合,具体步骤同 prism学习日记3
    这里贴一下源码
/// <summary>
    /// A catalog built from a configuration file.
    /// </summary>
    public class ConfigurationModuleCatalog : ModuleCatalog
    {
        /// <summary>
        /// Builds an instance of ConfigurationModuleCatalog with a <see cref="ConfigurationStore"/> as the default store.
        /// </summary>
        public ConfigurationModuleCatalog()
        {
            Store = new ConfigurationStore();
        }

        /// <summary>
        /// Gets or sets the store where the configuration is kept.
        /// </summary>
        public IConfigurationStore Store { get; set; }

        /// <summary>
        /// Loads the catalog from the configuration.
        /// </summary>
        protected override void InnerLoad()
        {
            if (Store == null)
            {
                throw new InvalidOperationException(Resources.ConfigurationStoreCannotBeNull);
            }

            EnsureModulesDiscovered();
        }

        private void EnsureModulesDiscovered()
        {
            ModulesConfigurationSection section = Store.RetrieveModuleConfigurationSection();

            if (section != null)
            {
                foreach (ModuleConfigurationElement element in section.Modules)
                {
                    IList<string> dependencies = new List<string>();

                    if (element.Dependencies.Count > 0)
                    {
                        foreach (ModuleDependencyConfigurationElement dependency in element.Dependencies)
                        {
                            dependencies.Add(dependency.ModuleName);
                        }
                    }

                    ModuleInfo moduleInfo = new ModuleInfo(element.ModuleName, element.ModuleType)
                    {
                        Ref = GetFileAbsoluteUri(element.AssemblyFile),
                        InitializationMode = element.StartupLoaded ? InitializationMode.WhenAvailable : InitializationMode.OnDemand
                    };
                    moduleInfo.DependsOn.AddRange(dependencies.ToArray());
                    AddModule(moduleInfo);
                }
            }
        }
    }

IModuleManager接口

/// <summary>
    /// Defines the interface for the service that will retrieve and initialize the application's modules.
    /// </summary>
    public interface IModuleManager
    {
        /// <summary>
        /// Gets all the <see cref="IModuleInfo"/> classes that are in the <see cref="IModuleCatalog"/>.
        /// </summary>
        IEnumerable<IModuleInfo> Modules { get; }

        /// <summary>
        /// Initializes the modules marked as <see cref="InitializationMode.WhenAvailable"/> on the <see cref="IModuleCatalog"/>.
        /// </summary>
        void Run();

        /// <summary>
        /// Loads and initializes the module on the <see cref="IModuleCatalog"/> with the name <paramref name="moduleName"/>.
        /// </summary>
        /// <param name="moduleName">Name of the module requested for initialization.</param>
        void LoadModule(string moduleName);

        /// <summary>
        /// Raised repeatedly to provide progress as modules are downloaded.
        /// </summary>
        event EventHandler<ModuleDownloadProgressChangedEventArgs> ModuleDownloadProgressChanged;

        /// <summary>
        /// Raised when a module is loaded or fails to load.
        /// </summary>
        event EventHandler<LoadModuleCompletedEventArgs> LoadModuleCompleted;
    }

上述接口定义了

  1. IEnumerable类型的modules属性:用来描述当前IModuleManager包含的modules
  2. run方法:从下面的源码看是先对整个应用程序的module解析到ModuleCatalog中,再将这些module中初始化类型是InitializationMode.WhenAvailable 的moudle进行逐一load操作
  3. LoadModule方法:可以手动加载指定名称的module
  4. LoadModuleCompleted事件:当module加载结束就会触发此事件
  5. ModuleDownloadProgressChanged事件:用来描述当前Module如果是从远程下载的,那么通过此事件能够报告当前Module进行下载的Progress
    modulemanager的实现类代码如下:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Prism.Properties;

namespace Prism.Modularity
{
    /// <summary>
    /// Component responsible for coordinating the modules' type loading and module initialization process.
    /// </summary>
    public partial class ModuleManager : IModuleManager, IDisposable
    {
        private readonly IModuleInitializer moduleInitializer;
        private IEnumerable<IModuleTypeLoader> typeLoaders;
        private HashSet<IModuleTypeLoader> subscribedToModuleTypeLoaders = new HashSet<IModuleTypeLoader>();

        /// <summary>
        /// Initializes an instance of the <see cref="ModuleManager"/> class.
        /// </summary>
        /// <param name="moduleInitializer">Service used for initialization of modules.</param>
        /// <param name="moduleCatalog">Catalog that enumerates the modules to be loaded and initialized.</param>
        public ModuleManager(IModuleInitializer moduleInitializer, IModuleCatalog moduleCatalog)
        {
            this.moduleInitializer = moduleInitializer ?? throw new ArgumentNullException(nameof(moduleInitializer));
            ModuleCatalog = moduleCatalog ?? throw new ArgumentNullException(nameof(moduleCatalog));
        }

        /// <summary>
        /// The module catalog specified in the constructor.
        /// </summary>
        protected IModuleCatalog ModuleCatalog { get; }

        /// <summary>
        /// Gets all the <see cref="IModuleInfo"/> classes that are in the <see cref="IModuleCatalog"/>.
        /// </summary>
        public IEnumerable<IModuleInfo> Modules => ModuleCatalog.Modules;

        /// <summary>
        /// Raised repeatedly to provide progress as modules are loaded in the background.
        /// </summary>
        public event EventHandler<ModuleDownloadProgressChangedEventArgs> ModuleDownloadProgressChanged;

        private void RaiseModuleDownloadProgressChanged(ModuleDownloadProgressChangedEventArgs e)
        {
            ModuleDownloadProgressChanged?.Invoke(this, e);
        }

        /// <summary>
        /// Raised when a module is loaded or fails to load.
        /// </summary>
        public event EventHandler<LoadModuleCompletedEventArgs> LoadModuleCompleted;

        private void RaiseLoadModuleCompleted(IModuleInfo moduleInfo, Exception error)
        {
            this.RaiseLoadModuleCompleted(new LoadModuleCompletedEventArgs(moduleInfo, error));
        }

        private void RaiseLoadModuleCompleted(LoadModuleCompletedEventArgs e)
        {
            this.LoadModuleCompleted?.Invoke(this, e);
        }

        /// <summary>
        /// Initializes the modules marked as <see cref="InitializationMode.WhenAvailable"/> on the <see cref="ModuleCatalog"/>.
        /// </summary>
        public void Run()
        {
            this.ModuleCatalog.Initialize();

            this.LoadModulesWhenAvailable();
        }


        /// <summary>
        /// Loads and initializes the module on the <see cref="IModuleCatalog"/> with the name <paramref name="moduleName"/>.
        /// </summary>
        /// <param name="moduleName">Name of the module requested for initialization.</param>
        public void LoadModule(string moduleName)
        {
            var module = this.ModuleCatalog.Modules.Where(m => m.ModuleName == moduleName);
            if (module == null || module.Count() != 1)
            {
                throw new ModuleNotFoundException(moduleName, string.Format(CultureInfo.CurrentCulture, Resources.ModuleNotFound, moduleName));
            }

            var modulesToLoad = this.ModuleCatalog.CompleteListWithDependencies(module);

            this.LoadModuleTypes(modulesToLoad);
        }

        /// <summary>
        /// Checks if the module needs to be retrieved before it's initialized.
        /// </summary>
        /// <param name="moduleInfo">Module that is being checked if needs retrieval.</param>
        /// <returns></returns>
        protected virtual bool ModuleNeedsRetrieval(IModuleInfo moduleInfo)
        {
            if (moduleInfo == null)
                throw new ArgumentNullException(nameof(moduleInfo));

            if (moduleInfo.State == ModuleState.NotStarted)
            {
                // If we can instantiate the type, that means the module's assembly is already loaded into
                // the AppDomain and we don't need to retrieve it.
                bool isAvailable = Type.GetType(moduleInfo.ModuleType) != null;
                if (isAvailable)
                {
                    moduleInfo.State = ModuleState.ReadyForInitialization;
                }

                return !isAvailable;
            }

            return false;
        }

        private void LoadModulesWhenAvailable()
        {
            var whenAvailableModules = this.ModuleCatalog.Modules.Where(m => m.InitializationMode == InitializationMode.WhenAvailable);
            var modulesToLoadTypes = this.ModuleCatalog.CompleteListWithDependencies(whenAvailableModules);
            if (modulesToLoadTypes != null)
            {
                this.LoadModuleTypes(modulesToLoadTypes);
            }
        }

        private void LoadModuleTypes(IEnumerable<IModuleInfo> moduleInfos)
        {
            if (moduleInfos == null)
            {
                return;
            }

            foreach (var moduleInfo in moduleInfos)
            {
                if (moduleInfo.State == ModuleState.NotStarted)
                {
                    if (this.ModuleNeedsRetrieval(moduleInfo))
                    {
                        this.BeginRetrievingModule(moduleInfo);
                    }
                    else
                    {
                        moduleInfo.State = ModuleState.ReadyForInitialization;
                    }
                }
            }

            this.LoadModulesThatAreReadyForLoad();
        }

        /// <summary>
        /// Loads the modules that are not initialized and have their dependencies loaded.
        /// </summary>
        protected virtual void LoadModulesThatAreReadyForLoad()
        {
            bool keepLoading = true;
            while (keepLoading)
            {
                keepLoading = false;
                var availableModules = this.ModuleCatalog.Modules.Where(m => m.State == ModuleState.ReadyForInitialization);

                foreach (var moduleInfo in availableModules)
                {
                    if ((moduleInfo.State != ModuleState.Initialized) && (this.AreDependenciesLoaded(moduleInfo)))
                    {
                        moduleInfo.State = ModuleState.Initializing;
                        this.InitializeModule(moduleInfo);
                        keepLoading = true;
                        break;
                    }
                }
            }
        }

        private void BeginRetrievingModule(IModuleInfo moduleInfo)
        {
            var moduleInfoToLoadType = moduleInfo;
            IModuleTypeLoader moduleTypeLoader = this.GetTypeLoaderForModule(moduleInfoToLoadType);
            moduleInfoToLoadType.State = ModuleState.LoadingTypes;

            // Delegate += works differently between SL and WPF.
            // We only want to subscribe to each instance once.
            if (!this.subscribedToModuleTypeLoaders.Contains(moduleTypeLoader))
            {
                moduleTypeLoader.ModuleDownloadProgressChanged += this.IModuleTypeLoader_ModuleDownloadProgressChanged;
                moduleTypeLoader.LoadModuleCompleted += this.IModuleTypeLoader_LoadModuleCompleted;
                this.subscribedToModuleTypeLoaders.Add(moduleTypeLoader);
            }

            moduleTypeLoader.LoadModuleType(moduleInfo);
        }

        private void IModuleTypeLoader_ModuleDownloadProgressChanged(object sender, ModuleDownloadProgressChangedEventArgs e)
        {
            this.RaiseModuleDownloadProgressChanged(e);
        }

        private void IModuleTypeLoader_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if ((e.ModuleInfo.State != ModuleState.Initializing) && (e.ModuleInfo.State != ModuleState.Initialized))
                {
                    e.ModuleInfo.State = ModuleState.ReadyForInitialization;
                }

                // This callback may call back on the UI thread, but we are not guaranteeing it.
                // If you were to add a custom retriever that retrieved in the background, you
                // would need to consider dispatching to the UI thread.
                this.LoadModulesThatAreReadyForLoad();
            }
            else
            {
                this.RaiseLoadModuleCompleted(e);

                // If the error is not handled then I log it and raise an exception.
                if (!e.IsErrorHandled)
                {
                    this.HandleModuleTypeLoadingError(e.ModuleInfo, e.Error);
                }
            }
        }

        /// <summary>
        /// Handles any exception occurred in the module typeloading process,
        /// and throws a <see cref="ModuleTypeLoadingException"/>.
        /// This method can be overridden to provide a different behavior.
        /// </summary>
        /// <param name="moduleInfo">The module metadata where the error happened.</param>
        /// <param name="exception">The exception thrown that is the cause of the current error.</param>
        /// <exception cref="ModuleTypeLoadingException"></exception>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1")]
        protected virtual void HandleModuleTypeLoadingError(IModuleInfo moduleInfo, Exception exception)
        {
            if (moduleInfo == null)
                throw new ArgumentNullException(nameof(moduleInfo));


            if (!(exception is ModuleTypeLoadingException moduleTypeLoadingException))
            {
                moduleTypeLoadingException = new ModuleTypeLoadingException(moduleInfo.ModuleName, exception.Message, exception);
            }

            throw moduleTypeLoadingException;
        }

        private bool AreDependenciesLoaded(IModuleInfo moduleInfo)
        {
            var requiredModules = this.ModuleCatalog.GetDependentModules(moduleInfo);
            if (requiredModules == null)
            {
                return true;
            }

            int notReadyRequiredModuleCount =
                requiredModules.Count(requiredModule => requiredModule.State != ModuleState.Initialized);

            return notReadyRequiredModuleCount == 0;
        }

        private IModuleTypeLoader GetTypeLoaderForModule(IModuleInfo moduleInfo)
        {
            foreach (IModuleTypeLoader typeLoader in this.ModuleTypeLoaders)
            {
                if (typeLoader.CanLoadModuleType(moduleInfo))
                {
                    return typeLoader;
                }
            }

            throw new ModuleTypeLoaderNotFoundException(moduleInfo.ModuleName, string.Format(CultureInfo.CurrentCulture, Resources.NoRetrieverCanRetrieveModule, moduleInfo.ModuleName), null);
        }

        private void InitializeModule(IModuleInfo moduleInfo)
        {
            if (moduleInfo.State == ModuleState.Initializing)
            {
                this.moduleInitializer.Initialize(moduleInfo);
                moduleInfo.State = ModuleState.Initialized;
                this.RaiseLoadModuleCompleted(moduleInfo, null);
            }
        }

        #region Implementation of IDisposable

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <remarks>Calls <see cref="Dispose(bool)"/></remarks>.
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Disposes the associated <see cref="IModuleTypeLoader"/>s.
        /// </summary>
        /// <param name="disposing">When <see langword="true"/>, it is being called from the Dispose method.</param>
        protected virtual void Dispose(bool disposing)
        {
            foreach (IModuleTypeLoader typeLoader in this.ModuleTypeLoaders)
            {
                if (typeLoader is IDisposable disposableTypeLoader)
                {
                    disposableTypeLoader.Dispose();
                }
            }
        }

        #endregion
    }
}

modulemanager在构造函数中包含了两个部分,IModuleInitializer接口和IModuleCatalog接口(上文已介绍过)

IModuleInitializer接口

该接口的定义:

    /// <summary>
    /// Declares a service which initializes the modules into the application.
    /// </summary>
    public interface IModuleInitializer
    {
        /// <summary>
        /// Initializes the specified module.
        /// </summary>
        /// <param name="moduleInfo">The module to initialize</param>
        void Initialize(IModuleInfo moduleInfo);
    }

可以看出是通过传入moduleinfo参数实现对module的初始化
具体实现过程如下:

using System;
using System.Globalization;
using Prism.Ioc;

namespace Prism.Modularity
{
    /// <summary>
    /// Implements the <see cref="IModuleInitializer"/> interface. Handles loading of a module based on a type.
    /// </summary>
    public class ModuleInitializer : IModuleInitializer
    {
        private readonly IContainerExtension _containerExtension;

        /// <summary>
        /// Initializes a new instance of <see cref="ModuleInitializer"/>.
        /// </summary>
        /// <param name="containerExtension">The container that will be used to resolve the modules by specifying its type.</param>
        public ModuleInitializer(IContainerExtension containerExtension)
        {
            this._containerExtension = containerExtension ?? throw new ArgumentNullException(nameof(containerExtension));
        }

        /// <summary>
        /// Initializes the specified module.
        /// </summary>
        /// <param name="moduleInfo">The module to initialize</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Catches Exception to handle any exception thrown during the initialization process with the HandleModuleInitializationError method.")]
        public void Initialize(IModuleInfo moduleInfo)
        {
            if (moduleInfo == null)
                throw new ArgumentNullException(nameof(moduleInfo));

            IModule moduleInstance = null;
            try
            {
                moduleInstance = this.CreateModule(moduleInfo);
                if (moduleInstance != null)
                {
                    moduleInstance.RegisterTypes(_containerExtension);
                    moduleInstance.OnInitialized(_containerExtension);
                }
            }
            catch (Exception ex)
            {
                this.HandleModuleInitializationError(
                    moduleInfo,
                    moduleInstance?.GetType().Assembly.FullName,
                    ex);
            }
        }

        /// <summary>
        /// Handles any exception occurred in the module Initialization process,
        /// This method can be overridden to provide a different behavior.
        /// </summary>
        /// <param name="moduleInfo">The module metadata where the error happened.</param>
        /// <param name="assemblyName">The assembly name.</param>
        /// <param name="exception">The exception thrown that is the cause of the current error.</param>
        /// <exception cref="ModuleInitializeException"></exception>
        public virtual void HandleModuleInitializationError(IModuleInfo moduleInfo, string assemblyName, Exception exception)
        {
            if (moduleInfo == null)
                throw new ArgumentNullException(nameof(moduleInfo));

            if (exception == null)
                throw new ArgumentNullException(nameof(exception));

            Exception moduleException;

            if (exception is ModuleInitializeException)
            {
                moduleException = exception;
            }
            else
            {
                if (!string.IsNullOrEmpty(assemblyName))
                {
                    moduleException = new ModuleInitializeException(moduleInfo.ModuleName, assemblyName, exception.Message, exception);
                }
                else
                {
                    moduleException = new ModuleInitializeException(moduleInfo.ModuleName, exception.Message, exception);
                }
            }

            throw moduleException;
        }

        /// <summary>
        /// Uses the container to resolve a new <see cref="IModule"/> by specifying its <see cref="Type"/>.
        /// </summary>
        /// <param name="moduleInfo">The module to create.</param>
        /// <returns>A new instance of the module specified by <paramref name="moduleInfo"/>.</returns>
        protected virtual IModule CreateModule(IModuleInfo moduleInfo)
        {
            if (moduleInfo == null)
                throw new ArgumentNullException(nameof(moduleInfo));

            return this.CreateModule(moduleInfo.ModuleType);
        }

        /// <summary>
        /// Uses the container to resolve a new <see cref="IModule"/> by specifying its <see cref="Type"/>.
        /// </summary>
        /// <param name="typeName">The type name to resolve. This type must implement <see cref="IModule"/>.</param>
        /// <returns>A new instance of <paramref name="typeName"/>.</returns>
        protected virtual IModule CreateModule(string typeName)
        {
            Type moduleType = Type.GetType(typeName);
            if (moduleType == null)
            {
                throw new ModuleInitializeException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.FailedToGetType, typeName));
            }

            return (IModule)_containerExtension.Resolve(moduleType);
        }
    }
}


核心是根据当前moduleinfo构造出一个Imodule对象,使用的时候需要调用imodule中定义的RegisterTypes和OnInitialized方法。如下所示:
在这里插入图片描述

leonablythe
关注 关注
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Prism系列】Module实现程序的插件化
songhuangong123的博客
09-06 1057
Prism提供的Module功能让我们方便的实现程序插件化。 1 新建一个类,让这个类实现接口IModule,并添加特性Module。这样在Prism框架进行扫描时就能找到这个类库。 2 实现IModule方法时,将需要关联到主体程序的类进行注册 3 在主体程序的APP中指定要扫描的类库路径。 4 主体程序中注入IModuleManager,对类库中的模块进行加载 5主体程序中注入IRegionManager,将模块中的控件与主体界面的Region进行关联。实现动态载入。
PrismModule
10-01 839
Prism的核心功能之一就是支持模块化应用程序开发(Modular Application Development),并且在运行时对各个模块进行动态管理。 使用Prism进行模块化开发首先要了解几个概念: 1.Module: Module是一些逻辑上相关的程序集或者资源文件的集合,在Silverlight程序中通常以xap文件为单位存在。而每一个Module中都需要有一个负责进行初始...
Prism框架(2)—Module使用
weixin_40867123的博客
05-23 1122
Prism框架(2)—Module使用
基于MVVM设计模式的Prism框架
最新发布
qq_47159522的博客
07-22 985
Prism 是一个用于构建富客户端桌面(WPF)和移动(Xamarin Forms)应用程序的框架,由微软提供。它基于微软的模式与实践(Microsoft Patterns & Practices)团队开发,并且是开源的。Prism 旨在简化应用程序开发过程,特别是那些遵循 MVVM(Model-View-ViewModel)模式的应用程序。Prism框架的主要特点有模块化MVVM 支持依赖注入导航事件聚合器命令行为服务定位器视图模型定位器区域和布局配置和初始化等。
WPF入门到跪下 第十一章 Prism(八)模块化管理-Module
jjailsa的博客
03-25 1651
Module是功能和资源的逻辑集合,其打包方式可以单独开发、测试、部署并集成到应用程序中。当随着项目较为庞大,有大量的不同业务、ViewViewModel时,就需要考虑根据不同业务进行程序集的拆分了,而Module就是帮助我们管理不同的程序集并集成到应用程序中。每个模块化管理的程序集中都有一个模块核心类,IModule的子类。主程序集通过加载这个IModule的子类,就可以将对应程序集集成到主程序集的prism框架中来。
Prism项目_2.Module使用
huaqianzkh的专栏
02-22 393
本质上来说,对于一个应用程序而言,特定功能的所有View、Logic、Service等都可以独立存在。那么意味着,每个独立的功能我们都可以称之为模块。而往往实际上,我们在一个项目中,他的结构通常都是所有的模块都在一个项目当中,这使得应用程序当中,我们难以区分单独的模块,它们似乎变成了一个整体。
第532篇--Prism Module学习_1
weixin_30757793的博客
08-11 679
程序设计中,我们讲究高内聚,低e合的设计原则,好把功能模块封装起来,作为一个整体来调用,这样在组成大型的程序设计时,便可以很好的复用和维护。今天一起学习Prism框架中的Modules这个概念。 首先是整个工程的架构: 在每一个模块中,我们都实现了Initialize这个方法,输入对应的说明信息: public class ModuleA:IModule { ...
WPF Prism页面导航实例(Bootstrapper,Shell,Module,Region,Navigation使用)
03-28
本篇将深入探讨Prism中的核心概念,包括Bootstrapper、Shell、Module、Region以及Navigation的使用,以及如何在实践中实现页面导航。 **1. Bootstrapper** Bootstrapper是Prism框架的启动点,它负责初始化整个应用...
WPF .Net6中使用Prism
06-01
通过这个示例项目,你可以学习如何在.NET 6的WPF应用中集成并使用Prism,从而实现更加灵活、模块化和可维护的代码结构。 总之,Prism框架为WPF开发者提供了一套强大的工具,使得在.NET 6中构建复杂应用变得更为简单...
vue-prism-component:使用prism.js和vue组件突出显示代码
05-08
yarn add vue-prism-component CDN: | 用法 首先,您需要在应用程序中的某个位置加载Prism : // yarn add prismjs import 'prismjs' import 'prismjs/themes/prism.css' 或者: < link rel =" stylesheet ...
Prism 学习:从本地目录加载 Module
刘默默的博客
04-04 1168
Prism 中,将外部模块加载到主程序有以下几种方式:Code、XAML、配置文件、指定模块目录;其中,如果要使用 Code 方式来加载 Module,则需要将该 Module 引用到当前项目中;而后面两种通过 XAML与配置文件,在原理上大体一致;本文主要讨论第四种方法,即通过指定 Module 所在的目录来加载 Module。     首先,我们需要在 Bootstrapper 类中
关于wpf SizeChanged不能触发的解决办法
深海狂鲨
10-23 4855
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen
Prism学习日记01
leonablythe的博客
12-29 279
第一次接触的一个新玩意,坚持学习一下写写记录好了 首先是上网址:https://prismlibrary.com/,介绍什么的百度就好了,总而言之就是MVVM模式的框架 下载和安装 官网的帮助文档已经写得很清楚啦,VS中下载对应扩展包就好了哦~ 初体验 嘛,毕竟是第一次使用,可以下载一些例子看看,帮助文档里面有给出github的链接,一键打包带走就好了!本人学的是WPF,所以就下载了对应的文件。 点击打开sln项目就能大开眼界啦! 点击这个红框框就能切换运行项目!看起来更方便~ 全部浏览一遍会发现主要是界
Prism学习日记02 创建一个prism结构的wpf工程
leonablythe的博客
01-07 506
帮助文档中向我们介绍了prism的扩展包以及开发需要用到的工具,这里可以利用Prism Template Pack进行快速创建一个Prism结构的WPF工程 安装后创建一个空项目即可。 几个比较重要的概念: 1.shell:模块的宿主程序,可以理解为mainwindow,内部装载各个模块。通常实现了公共程序服务和基本代码 2.region:一个逻辑占位,可以理解为一个界面中的容器,各组件可以被放在指定的region 3.regionmanager:使用RegionAdapter和RegionBehavio
WPF Prism导航操作,导航传参,导航拦截,导航日志笔记
weixin_44442366的博客
03-23 3068
导航传参 引入using Prism.Regions;命名控件 /// <summary> /// 打开导航并传参 /// </summary> /// <param name="obj">要打开的导航模块名</param> private void Open(string obj) { //定义传参变量 NavigationPar
[Prism框架实用分享]如何在Prism应用程序中使用日志
weixin_30586085的博客
03-03 726
前言 在Prism中有关日志的命名空间: Microsoft.Practices.Prism.Logging 在Prism中,你可以使用Prism自带的Logger(比如TextLogger等),也可以使用自定义的Logger(比如Log4Net等),但所有的Logger都比须实现接口 ILoggerFacade 。下面就以Log4Net为例,实现一个自定义的Logger,并将它应用...
module4,Prism 4学习笔记之Module
xieqinghai的专栏
01-19 1292
在开发过程中将程序分解,使其变成一个个独立的模块,有助于代码的复用,也提高了可维护性。并且可以由多人协同工作,各自开发不同的模块,最后组装到一起,这样也大大提高了生产率。 Prism中有Module这个概念,通过将程序分解为一个个Module,并采用一种松散耦合的方式来将它们组合到一起,可以达到使程序更加灵活、易于测试、易于维护等目的。 下面先看一下两个非常重要的概念: Modules: M
第533篇--Prism Module学习_2
weixin_30786657的博客
08-11 207
接着上文Prism Module讲,本文主要讲述Prism Modules在Boot strapper中的配制方式,可以用ConfigureModuleCatalog 或是CreateModuleCatalog方法来配制全文中的Module Catalog. 在第一个方法中,我们用代码的形式,把B ,C Module加载到了工程,在后一个模式中,我们把Module E配制在XAML...
prism框架里module太多启动速度过慢
a859501的博客
11-21 1206
一个基于prism框架desktop项目,总共有100多个module。程序启动的时候有几秒钟的delay。 用的DirectoryModuleCatalog类从本地目录中装载module的程序集。 附:DirectoryModuleCatalog装载部分源代码 View Code //============================================...
写文章

热门文章

  • NI-VISA概览 7889
  • C#控制台程序通过VISA对电源进行自动化控制 6697
  • WPF界面侧边栏弹窗效果 2208
  • 修改vs项目生成的软件版本号 1619
  • 关于wpf界面列表刷新时间过长,卡顿的问题 1264

最新评论

  • C#控制台程序通过VISA对电源进行自动化控制

    leonablythe: 这个应该看具体设备,usb 串口之类的应该不需要配置可以直接检测到,网络设备肯定是需要根据设备ip 对本机ip 地址进行修改配置的,一般保证ip 前三个地址一致就可以了

  • C#控制台程序通过VISA对电源进行自动化控制

    weixin_51279799: 你好 请问一下 编程完以后需要在NIMAX中进行一些配置吗比如配置ip什么的 怎么配置呢

  • 关于指针的一些注意点(持续记录)

    CSDN-Ada助手: 恭喜您写了第15篇博客!标题为“关于指针的一些注意点(持续记录)”,看起来很有深度和实用性。在这篇博客中,您提到了一些关于指针的注意事项,这对于学习和使用指针的人来说无疑是非常有帮助的。 我想说,您的持续创作态度非常值得称赞。通过记录自己学习的过程和经验,不仅可以帮助他人解决问题,同时也能够加深自己的理解和记忆。我期待着您未来更多关于指针的文章,或者是其他与编程相关的主题。或许您可以分享一些指针在实际项目中的应用案例,或者是与指针相关的高级技巧和技术。 谦虚而持续地创作下去,我相信您的博客会越来越受到读者的喜爱和关注。加油!

  • 关于wpf界面列表刷新时间过长,卡顿的问题

    leonablythe: 我觉得如果等全部生成的话慢是一定的,可以在显示刷新上做手脚,比如初次只加载可视部分,其余部分可以分线程分批加载,至少在观感上会舒适一点?和我这个应该是类似的道理表情包

  • 关于wpf界面列表刷新时间过长,卡顿的问题

    cj5035: 楼主这篇是解决在已有控件上数据刷新问题嘛?有没有遇到过大批量控件生成缓慢的问题?控件是单线程动态new出来,不能复用的情况

最新文章

  • prism学习日记06 消息传递和触发机制
  • 关于指针的一些注意点(持续记录)
  • prism学习日记05 切换UI(导航)
2024年1篇
2023年4篇
2022年9篇
2021年2篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家五常玻璃钢雕塑定做玻璃钢雕塑人物报价清单美陈玻璃钢卡通雕塑手工制作商场美陈怎么搭建青海玻璃钢景观雕塑公司山东广场玻璃钢雕塑价格长沙水果玻璃钢雕塑制作江苏景区玻璃钢雕塑批发湖北猪猪侠玻璃钢雕塑时尚的玻璃钢雕塑玻璃钢花盆的简介黑龙江玻璃钢雕塑喷漆玻璃钢香蕉雕塑生产河南装饰商场美陈制造唐山玻璃钢卡通雕塑价格开县欧式人物玻璃钢雕塑吉安玻璃钢牛雕塑成都鼎湖玻璃钢人物雕塑陕西大型玻璃钢景观雕塑温州小区玻璃钢雕塑制作玻璃钢仿真盘子雕塑长春玻璃钢雕塑公司哪家好咸宁市玻璃钢雕塑定制沧州玻璃钢广场雕塑厂家河北节庆商场美陈订购山西创意玻璃钢雕塑越城玻璃钢花盆花器户外玻璃钢雕塑定做厂家山东佛像玻璃钢雕塑优势鹤壁玻璃钢花盆批发香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化