C# “如何加载WPF应用程序资源”;via Code";(不是“通过XAML”)从单独的组件

C# “如何加载WPF应用程序资源”;via Code";(不是“通过XAML”)从单独的组件,c#,.net,wpf,xaml,app.xaml,C#,.net,Wpf,Xaml,App.xaml,我有一个WPF应用程序(称之为启动器),希望通过代码而不是XAML来指定额外的应用程序资源(例如额外的视图、组件和内容)。此外,这些资源由第二个程序集定义(而不是定义App.xaml的同一个程序集) 目前,我们在App.xaml中对此进行了定义: <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries>

我有一个WPF应用程序(称之为启动器),希望通过代码而不是XAML来指定额外的应用程序资源(例如额外的视图、组件和内容)。此外,这些资源由第二个程序集定义(而不是定义
App.xaml
的同一个程序集)

目前,我们在
App.xaml
中对此进行了定义:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/GUI;component/Common/ViewResources.xaml" />
            <ResourceDictionary Source="/GUI;component/Common/ResourceDictionary.xaml" />
            <ResourceDictionary Source="/Components;component/Common/ResourceDictionary.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

这是可行的,但这不是我想要做的。要解析这些资源,我需要在URL中指定程序集引用,或在EXE中包含/复制资源(包含
App.xaml
的程序集)

是否有办法在GUI端的代码中设置/初始化应用程序资源? 还有其他想法吗?

您必须假设启动程序已经输入了“App::Run”,您必须在该事件发生后加载必要的UI资源,并且必须保持处理中。


有3种明显的解决方案是不可接受的:

  • 在GUI中添加词典,并将其合并到所有视图中(例如,扩展现有UI)

  • 由于启动器已经是一个应用程序,我们无法在GUI.Start中执行类似操作(例如,运行第二个正在运行的应用程序):

    公开作废开始() { App App=新App(); app.Run(); }

  • 两者(Launcher和GUI)都需要保持在同一个流程中,因此这样的解决方案是不可接受的(例如,在流程外启动第二个应用程序):

    进程myProc; myProc=Process.Start(“GUI.exe”)


  • 一位同事刚刚提出了一个解决方案,其实很简单:

    提供属性GUI.Resources,用于设置所有启动器应用程序资源:

    public ResourceDictionary Resources
    {
        get
        {
            ResourceDictionary resourceGUIView = new ResourceDictionary();
            resourceGUIView.Source = new Uri("/GUI;component/Common/ViewResources.xaml", UriKind.RelativeOrAbsolute);
            ResourceDictionary resourceGUI = new ResourceDictionary();
            resourceGUI.Source = new Uri("/GUI;component/Common/ResourceDictionary.xaml", UriKind.RelativeOrAbsolute);
            ResourceDictionary resourceComponent = new ResourceDictionary();
            resourceComponent.Source = new Uri("/Component;component/Common/ResourceDictionary.xaml", UriKind.RelativeOrAbsolute);
    
            ResourceDictionary generalResource = new ResourceDictionary();
    
            generalResource.MergedDictionaries.Add(resourceGUIView);
            generalResource.MergedDictionaries.Add(resourceGUI);
            generalResource.MergedDictionaries.Add(resourceComponent);
    
            return generalResource;
        }
    }
    
    然后在启动器的App.xaml.cs中调用它:

    protected override void OnStartup(StartupEventArgs e)
    {
        this.Resources = this.context.GUI.Resources;
    
        ...
    
        base.OnStartup(e);
    }
    

    需要考虑的其他一些方法:

    • 要指定程序集引用,这适用于“通过XAML”和“通过代码”两种情况

    • 使用
      条目创建一个应用程序配置,该条目将目标UI入口点指定为“键入全名”,例如“MyNamespace.InitializerClassName,MyAssemblyName”,然后将其作为参数传递给调用
      Activator.CreateInstance()
      。此类型的构造函数将执行必要的初始化(或抛出)

    • 创建一个专门构建的接口,并使用反射来定位另一个程序集的“初始值设定项类型”。然后在该接口上调用一个众所周知的方法来执行UI初始化

    • 创建一个专门构建的属性,并使用反射来定位另一个程序集的“初始值设定项方法”。然后调用该方法执行UI初始化

    • 创建辅助
      AppDomain
      并在辅助
      AppDomain
      上下文中的新线程上调用
      App.Run()
      。在调用
      App.Run()
      之前,您可能必须利用
      MarshallByRefObject
      执行远程调用以创建线程、处理异常并扩展主机环境。这种方法将允许启动器和目标UI在相同的物理进程空间中共存,允许启动器扩展运行时环境,并允许目标UI在代码中执行初始化

    这些方法都不一定需要对UI程序集进行编译时引用,从而使启动器可以从一个UI移植到下一个UI(除非在包URI或App.Config中指定程序集名称)


    看起来OPs自己的解决方案在编译时与目标程序集紧密耦合(没有配置/发现/反射过程)删除目标UI程序集会破坏构建/编译。

    在WPF应用程序中启动业务服务有什么问题?我已经把这个问题重读了4遍,但我仍然完全不知道你想实现什么。他试图从一个非UI特定的启动器中动态加载UI。这很难理解,但如果你以前做过,也很明显他想尝试什么。如果你不明白,没有理由否决,有人只需要修改这个问题。为什么这与XAML有什么不同?因为启动程序不需要知道GUI需要哪些资源,就像GUI提供这些资源一样。但基本上我们会有相同的解决方案,只有资源的定义来自GUI,就像我想要的那样。@FábioFerreira作为旁白,您也可以通过在Uri中指定程序集引用从XAML执行此操作。如果已经有一个关于如何做的问题,我不会感到惊讶。