2

我有一个 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 端设置/初始化-应用程序资源?还有什么想法吗?

您必须假设 Launcher 已经进入“App::Run”,您必须在此事件发生后加载必要的 UI 资源,并且您必须保持在进程中。


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

  1. 在 GUI 中添加字典并将其合并到所有视图中(例如扩展现有 UI)

  2. 由于启动器已经是一个应用程序,我们不能在 GUI.Start 中做这样的事情(例如在进程中运行第二个应用程序):

    公共无效开始(){应用程序=新应用程序();应用程序运行();}

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

    处理 myProc;myProc = Process.Start("GUI.exe");

4

2 回答 2

1

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

  • 修改 Pack URI以指定程序集引用,这适用于“通过 XAML”和“通过代码”情况。

  • <appSettings/>使用将目标 UI 入口点指定为“类型全名”(例如“MyNamespace.InitializerClassName,MyAssemblyName”)的条目创建一个 app-config ,然后将其作为参数传递给 call Activator.CreateInstance()。这种类型的构造函数将执行必要的初始化(或抛出。)

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

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

  • 创建一个辅助对象并在辅助对象的上下文中AppDomain调用App.Run()一个NEW THREADAppDomain。在MarshalByRefObject调用App.Run(). 这种方法将允许启动器和目标 UI 在同一物理进程空间中共存,允许启动器扩展运行时环境,并允许目标 UI 在代码中执行初始化。

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

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

于 2014-08-04T21:05:33.330 回答
1

一位同事刚刚提出了一个解决方案,实际上它很简单:

提供一个属性 GUI.Resources,用于设置所有 Launcher App 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;
    }
}

然后在 Launcher 的 App.xaml.cs 中调用它:

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

    ...

    base.OnStartup(e);
}
于 2013-12-13T16:45:43.577 回答