Prism中如何控制模块初始化的顺序

2023-11-26

我将 Prism V2 与 DirectoryModuleCatalog 结合使用,并且需要按特定顺序初始化模块。所需的顺序由每个 IModule 实现上的属性指定。

这样,当每个模块初始化时,它们会将其视图添加到 TabControl 区域中,并且选项卡的顺序需要确定并由模块作者控制。

该顺序并不意味着依赖关系,而只是它们初始化的顺序。换句话说:模块 A、B 和 C 的优先级可能分别为 1、2 和 3。 B 不依赖于 A - 它只需要加载到 TabControl 区域中after答:这样我们就有了确定且可控的选项卡顺序。另外,B 在运行时可能不存在;因此它们将加载为 A, C,因为优先级应确定顺序 (1, 3)。如果我使用 ModuleDependency,那么模块“C”将无法加载其所有依赖项。

我可以管理如何对模块进行排序的逻辑,但我不明白where放置所说的逻辑。


我不喜欢使用 ModuleDependency 的想法,因为这意味着当模块 b 不存在时,模块 a 不会加载,而实际上没有依赖项。相反,我创建了一个优先级属性来装饰模块:

/// <summary>
/// Allows the order of module loading to be controlled.  Where dependencies
/// allow, module loading order will be controlled by relative values of priority
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class PriorityAttribute : Attribute
{
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="priority">the priority to assign</param>
    public PriorityAttribute(int priority)
    {
        this.Priority = priority;
    }

    /// <summary>
    /// Gets or sets the priority of the module.
    /// </summary>
    /// <value>The priority of the module.</value>
    public int Priority { get; private set; }
}

然后我像这样装饰模块:

[Priority(200)]
[Module(ModuleName = "MyModule")]
public class MyModule : IModule

我创建了 DirectoryModuleCatalog 的新后代:

/// <summary>
/// ModuleCatalog that respects PriorityAttribute for sorting modules
/// </summary>
[SecurityPermission(SecurityAction.InheritanceDemand), SecurityPermission(SecurityAction.LinkDemand)]
public class PrioritizedDirectoryModuleCatalog : DirectoryModuleCatalog
{
    /// <summary>
    /// local class to load assemblies into different appdomain which is then discarded
    /// </summary>
    private class ModulePriorityLoader : MarshalByRefObject
    {
        /// <summary>
        /// Get the priorities
        /// </summary>
        /// <param name="modules"></param>
        /// <returns></returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")]
        public Dictionary<string, int> GetPriorities(IEnumerable<ModuleInfo> modules)
        {
            //retrieve the priorities of each module, so that we can use them to override the 
            //sorting - but only so far as we don't mess up the dependencies
            var priorities = new Dictionary<string, int>();
            var assemblies = new Dictionary<string, Assembly>();

            foreach (ModuleInfo module in modules)
            {
                if (!assemblies.ContainsKey(module.Ref))
                {
                    //LoadFrom should generally be avoided appently due to unexpected side effects,
                    //but since we are doing all this in a separate AppDomain which is discarded
                    //this needn't worry us
                    assemblies.Add(module.Ref, Assembly.LoadFrom(module.Ref));
                }

                Type type = assemblies[module.Ref].GetExportedTypes()
                    .Where(t => t.AssemblyQualifiedName.Equals(module.ModuleType, StringComparison.Ordinal))
                    .First();

                var priorityAttribute =
                    CustomAttributeData.GetCustomAttributes(type).FirstOrDefault(
                        cad => cad.Constructor.DeclaringType.FullName == typeof(PriorityAttribute).FullName);

                int priority;
                if (priorityAttribute != null)
                {
                    priority = (int)priorityAttribute.ConstructorArguments[0].Value;
                }
                else
                {
                    priority = 0;
                }

                priorities.Add(module.ModuleName, priority);
            }

            return priorities;
        }
    }

    /// <summary>
    /// Get the priorities that have been assigned to each module.  If a module does not have a priority 
    /// assigned (via the Priority attribute) then it is assigned a priority of 0
    /// </summary>
    /// <param name="modules">modules to retrieve priorities for</param>
    /// <returns></returns>
    private Dictionary<string, int> GetModulePriorities(IEnumerable<ModuleInfo> modules)
    {
        AppDomain childDomain = BuildChildDomain(AppDomain.CurrentDomain);
        try
        {
            Type loaderType = typeof(ModulePriorityLoader);
            var loader =
                (ModulePriorityLoader)
                childDomain.CreateInstanceFrom(loaderType.Assembly.Location, loaderType.FullName).Unwrap();

            return loader.GetPriorities(modules);
        }
        finally
        {
            AppDomain.Unload(childDomain);
        }
    }

    /// <summary>
    /// Sort modules according to dependencies and Priority
    /// </summary>
    /// <param name="modules">modules to sort</param>
    /// <returns>sorted modules</returns>
    protected override IEnumerable<ModuleInfo> Sort(IEnumerable<ModuleInfo> modules)
    {
        Dictionary<string, int> priorities = GetModulePriorities(modules);
        //call the base sort since it resolves dependencies, then re-sort 
        var result = new List<ModuleInfo>(base.Sort(modules));
        result.Sort((x, y) =>
            {
                string xModuleName = x.ModuleName;
                string yModuleName = y.ModuleName;
                //if one depends on other then non-dependent must come first
                //otherwise base on priority
                if (x.DependsOn.Contains(yModuleName))
                    return 1; //x after y
                else if (y.DependsOn.Contains(xModuleName))
                    return -1; //y after x
                else 
                    return priorities[xModuleName].CompareTo(priorities[yModuleName]);
            });

        return result;
    }
}

最后,我更改了引导程序以使用这个新目录:

    /// <summary>Where are the modules located</summary>
    /// <returns></returns>
    protected override IModuleCatalog GetModuleCatalog()
    {
        return new PrioritizedDirectoryModuleCatalog() { ModulePath = @".\Modules" };
    }

我不确定加载程序集的东西是否是最好的方法,但它似乎有效......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Prism中如何控制模块初始化的顺序 的相关文章

  • Visual Studio 2022 - 编译旧应用程序时出错

    我们正在尝试在 Visual Studio 2022 中使用 VB6 32 位应用程序 编译 2002 年以来非常旧的应用程序 我们需要调试此应用程序并能够在 Windows 10 计算机上运行此应用程序 编译时 我们发现以下错误 这似乎是
  • Spring.NET 和构造函数拦截器

    我正在尝试在构造时对对象进行一些 AOP 并找到了 IConstructorInterceptor 这对于我想要的东西来说是完美的 但它似乎不起作用 http jira springframework org browse SPRNET 2
  • StreamReader,C#,peek

    我有一个 StreamReader 它偶尔会检查它是否有更多内容可以从简单的文本文件中读取 它使用 peek 属性 问题是 当我使用 peek 时 位置发生了变化 尽管不应该发生 FileStream m fsReader new File
  • 获取代码中的绑定结果

    我可能正在以错误的方式寻找这个 但是 有没有办法通过代码获取绑定的结果值 可能是一些显而易见的东西 但我就是找不到它 您只需致电ProvideValue的绑定方法 困难的部分是你需要通过有效的IServiceProvider到方法 编辑 实
  • 重写 WPF 工具包图表中的 DataPointStyle

    我想覆盖DataPointStyle of the LineSeries在我的 WPF 工具包中Chart
  • DotNET 应用程序中的 GDI 句柄

    我的纯 DotNET 库作为非托管桌面应用程序中的插件运行 我收到了稳定的 虽然低 崩溃报告流 这些报告似乎表明 GDI 句柄存在问题 错误消息中的字体等 恢复为系统字体 各种控件的显示崩溃 不久后发生大规模崩溃 我的窗体几乎没有控件 但我
  • C# Julian 日期解析器

    我在电子表格中有一个单元格 它是 Excel 中的日期对象 但当它来自 C1 的 xls 类时 它会变成双精度型 类似于 2009 年 1 月 7 日的 39820 0 我读到这是儒略日期格式 有人可以告诉我如何在 C 中将其解析回 Dat
  • 如何在Wpf中的用户控件中调用MahApps Metro对话框

    当我尝试调用 MahApps Metro 对话框时 我在传递值时遇到错误 在传递参数时调用对话框控制时我需要传递 Metrowindow 参数 但我需要在用户控件中调用它 下面是当我需要对话框控制时我将调用的方法 public async
  • WPF HierarchicalDataTemplate 不会在属性更改时更新 ItemsSource

    这是一些 XAML
  • 找不到 Microsoft.Office.Interop Visual Studio

    我正在开发一个使用 C 发送电子邮件的应用程序 该应用程序将能够使用邮件模板等 问题是我无法找到任何 Office Interop 引用 这意味着我无法使用 Outlook 我的计算机上安装了 Office 但我也尝试从此链接安装 PIAh
  • 同一服务器上的多个.NET版本

    所以我一直都知道在一台计算机 客户端或服务器 上运行多个版本的 NET 框架是可以的 这个问题 https stackoverflow com questions 407306 running many versions of net on
  • 使 DataTemplate 可混合

    如何为 ViewModel 制作可混合的数据模板 可在表达式混合中设计 当我转到资源并尝试直接编辑数据模板时 我在绘图板上看到的只是一个空白矩形 这是因为 DataTemplate 没有绑定到任何东西 当然 我可以创建一个 UserCont
  • 当我使用 Image.FromFile() 时 FileNotFound

    我在这种情况下使用 Image FromFile string 方法 using System using System Collections Generic using System ComponentModel using Syste
  • “你好世界!!”在 .NET 4 中生成 3500 个页面错误

    我正在运行 Windows Vista 和 Visual Studio 2010 使用 NET 4 2 GB RAM 和大约 800 MB 可用空间 我创建了一个 Windows 窗体应用程序 但没有向其中添加任何代码 只需在发布模式下编译
  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • VB.NET 中的静态方法实现

    我很困惑Static在 VB NET 中的实现 在 C 中 我们可以创建静态类和静态方法来为我们的应用程序编写实用方法 现在 VB NET 让我们创建Module代替静态类 如果我们在模块中创建一个方法 默认情况下它会变成静态的 但在我的应
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite

随机推荐

  • 带请求正文的 Java HTTP DELETE

    我有一个外部 API 它使用 DELETE 和正文 JSON 我利用 Postman REST 客户端并通过请求正文完成删除 效果很好 我正在尝试使用一种方法自动化此功能 我尝试使用 HttpURLConnection 进行类似的 GET
  • Linux 中每个进程的最大线程数?

    Linux下一个进程最多可以创建多少个线程 如何 如果可能 修改该值 Linux 没有每个进程单独的线程限制 只是对系统上进程总数的限制 线程本质上只是 Linux 上具有共享地址空间的进程 您可以这样查看 cat proc sys ker
  • 在 `__enter__` 中返回除 `self` 以外的值是反模式吗?

    下列的这个相关问题 虽然总是有一些库以独特的方式使用语言功能的例子 但我想知道是否返回除self in an enter 方法应被视为反模式 在我看来 这似乎是一个坏主意的主要原因是它使包装上下文管理器出现问题 例如 在 Java 中 也可
  • 带最大化按钮的 Java 模式窗口

    如何创建一个模态窗口并具有最大化按钮 那么是否可以创建一个模态JFrame或创建一个JDialog带最大化按钮 在大多数外观和感觉上 模态窗口 例如JDialog 没有最大化按钮只是因为它们根本不应该被最大化 或最小化 可以通过一些技巧来添
  • 为什么main方法被标记为public?

    我有一个问题 为什么 main 方法被标记为public 根据 stackoverflow 上的答案 它被声明为static 该方法是静态的 因为否则会产生歧义 应该调用哪个构造函数 但是 任何人都可以解释为什么要声明它public alw
  • angular2:如何按条件手动添加css文件到index.html?

    下面的代码是样式的定义 我想按条件将以上文件添加到 src index html 中的 中 如何为每个设备应用一个 css 文件 如您所知 我无法在 index html 中使用 条件 代码 注意 我不会使用下面的方法 in angular
  • 为什么nodejs HTTP响应中不能写汉字?

    这是我的小代码 var http require http var port 9002 var host ip
  • 如何在不使用应用服务的应用设置的情况下保护Azure客户端ID和秘密

    我正在使用 Azure KeyVault 来存储我的数据库凭据 现在为了访问它 我在服务代码中硬编码了客户端 ID 和客户端密钥 我怎样才能避免这种硬编码 因为它不安全 1 I don t want to store client id a
  • IntentService调用AsyncTask的问题

    我创造了IntentService课堂和表演asyncTask但出现异常时onPreExecute 在此代码行调用pDialog show AsyncHandlerService类 public class AsyncHandlerServ
  • 将字符串转换为 Google 电子表格中的公式

    我花了 10 多个小时阅读并尝试不同的选择 但没有成功 我有这个字符串 这实际上是其他公式生成的字符串 QUERY IMPORTRANGE A1 D 1 IMPORTRANGE A2 D 1 IMPORTRANGE A3 D 1 IMPOR
  • 如何定义 XmlSerializer 使用的区域性

    我使用以下代码反序列化 xml 配置文件 Create object by deserializing the given xml document var serializer new XmlSerializer typeof Confi
  • 如何确保只在 virtualenv 中调用 pip?

    当我不在 virtualenv 中时 如何防止意外调用 pip 我写了下面的脚本称为pip并将其添加到我的 bin 这是在我的 pip 之前 PATH This script makes sure I don t accidentally
  • Application.Current.Shutdown() 没有

    标题就是关于这个的 WPF 应用程序 带有一些用于 IPC 的 WCF 内容 我打电话Application Current Shutdown 并且应用程序继续愉快地运行 我想Shutdown本来应该是势不可挡的 也许是因为它是从后台线程调
  • 为什么 docker exec 结合 STDERR 和 STDOUT 流

    这是使用输出 stderr 的示例docker exec 并将输出发送到 STDOUT docker exec t 09b24cd7fa69 ls nosuchfile 1 gt docker out 2 gt docker err cat
  • R 舍入到最接近的 0.5 或 0.1

    我有一个股票价格数据集 已四舍五入到小数点后两位 1234 56 我现在正在尝试四舍五入到每只股票都不同的特定值 这里有些例子 Current Stock Price Minimum Tick Increment Desired Outpu
  • python2 和 python3 之间的可移植元类

    我正在尝试让 python2 程序在 python3 中工作 它具有以下元类定义 这在 Py2 上运行得很好 让它与 py2 和 py3 兼容的 最佳 方法是什么 它在单元测试中失败了 try raise Actor DoesNotExis
  • Java是“按引用传递”还是“按值传递”?

    我一直认为Java使用引用传递 然而 我读到一篇博文它声称 Java 使用值传递 我认为我不明白作者所做的区分 解释是什么 术语 按值传递 和 按引用传递 有特殊之处 精确定义计算机科学中的含义 这些含义与许多人第一次听到这些术语时的直觉不
  • 在“/kafka/kafka_2.12-2.3.0/config/zookeeper_jaas.conf”中找不到名为“Server”的 JAAS 配置节

    当我从 kakfa 2 12 2 3 0 中的包运行 Zookeeper 时 出现以下错误 export KAFKA OPTS Djava security auth login config kafka kafka 2 12 2 3 0
  • 在 AngularJS 中使用 ngInfiniteScroll 指令实现反向无限滚动

    我想使用ngInfiniteScroll来自这里的指令 http binarymuse github io ngInfiniteScroll 在我的 Angular js 应用程序中实现反向无限滚动 就像在聊天小部件中一样 然而 该指令的文
  • Prism中如何控制模块初始化的顺序

    我将 Prism V2 与 DirectoryModuleCatalog 结合使用 并且需要按特定顺序初始化模块 所需的顺序由每个 IModule 实现上的属性指定 这样 当每个模块初始化时 它们会将其视图添加到 TabControl 区域