装配依赖问题

Assembly dependencies issue

情况:

我有树项目(ZShared、ZSearcher 和 ZClient),它们将在其中相互引用。

ZShared 是一个包含一些样式和资源的通用 DLL 程序集。

ZSearcher 也是一个带有一些 WPF 控件的 DLL 程序集。

ZClient 理论上可以是任何东西(WPF 应用程序、Winforms、Excel 等)出于测试目的我将其作为 WPF 应用程序。

问题:

当我在 ZSearcher 中引用 ZShared 时,它会生成两个 DLL 文件:ZShared.DLL 和 ZSearcher.DLL

在ZClient中引用ZSearcher时,只有ZSearcher被复制到ZClient文件夹中。这也可以通过引用 ZShared 来解决。

但我希望 ZSearcher 作为一个独立的应用程序运行。就像当 ZSearcher 被引用时,依赖项应该自动跟随。

因此我认为也许使用反射而不是引用可以解决问题。但是反射会发生完全相同的问题。

System.Windows.Markup.XamlParseException HResult=0x80131501
Message='Set property 'System.Windows.ResourceDictionary.Source' threw an exception.' Line number '10' and line position '18'.
Source=PresentationFramework
StackTrace: at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri) at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri) at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream) at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) at ZSearcher.SearcherWindow.InitializeComponent() in C:\Users\nn\Desktop\WorkSpaceVS\TestApplication\ZSearcher\SearcherWindow.xaml:line 1

Inner Exception 1: FileNotFoundException: Could not load file or assembly 'ZShared, Culture=neutral' or one of its dependencies. The system cannot find the file specified.

问题重现:

创建一个.NET-FrameworkC#DLL程序集项目(ZShared)。此程序集仅包含一个 ResourceDictionary:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <SolidColorBrush x:Key="ZSolidColorBrushRed" Color="Red"/>
    <Style x:Key="ZButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</ResourceDictionary>

创建另一个 .NET-Framework C# DLL 程序集项目 (ZSearcher)。该程序集包含一个 Window 和一个 Class:

Searcher.cs class:

namespace ZSearcher
{
    public static class Searcher
    {
        public static object Search(string param)
        {
            var window = new SearcherWindow();
            window.ShowDialog();

            return null;
        }
    }
}

SearcherWindow.xaml:

<Window x:Class="ZSearcher.SearcherWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Height="300" Width="500"
         Title="ZSearcher">

   <Window.Resources>
       <ResourceDictionary>
           <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary Source="pack://Application:,,,/ZShared;component/ZResources.xaml"/>
           </ResourceDictionary.MergedDictionaries>
       </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <StackPanel Margin="20">
            <TextBlock Text="SolidColorBrush test" Foreground="{DynamicResource ZSolidColorBrushRed}"/>
            <Button Content="Button style test" Style="{DynamicResource ZButtonStyle}"/>
        </StackPanel>
    </Grid>
</Window>

在 ZSearcher 项目中引用 ZShared.DLL。

创建一个 .NET-Framework WPF C# 应用程序。此应用仅包含主窗口。

MainWindow.xaml:

<Window x:Class="ZClient.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ZClient" Width="400" Height="200">
    <Grid>
        <Button Content="Open searcher" Click="OpenSearcher_Click" Width="100" Height="30"/>
    </Grid>
</Window>

MainWindow.cs

using System.Reflection;
using System.Windows;
using ZSearcher;

namespace ZClient
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OpenSearcher_Click(object sender, RoutedEventArgs e)
        {
            //Referenced tester
            var referenceTest = Searcher.Search("Test");

            //Reflection tester
            var test = Test("Search");
        }

        private static object Test(string methodName)
        {
            var assembly = Assembly.LoadFrom(@"C:\Users\nn\Desktop\WorkSpaceVS\TestApplication\ZSearcher\bin\Debug\ZSearcher.DLL");
            var type = assembly.GetType("ZSearcher.Searcher");

            if (type == null) return null;
            var methodInfo = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);

            if (methodInfo == null) return null;
            var parametersArray = new object[] { "Test" };

            return methodInfo.Invoke(null, parametersArray);
        }
    }
}

问题:

如何使此 ZSearcher 程序集独立运行?

当 MSBuild 生成解决方案时,它需要在 ZSearcher 和 ZShared 之间有一个代码级引用,以便正确检测依赖关系并将其复制到 ZClient bin 文件夹。

一些人会创建一个虚拟代码参考来解决这个问题。

using ZShared;

namespace ZSearcher
{
    public static class Searcher
    {
        static Searcher()
        {
            // Reference something from ZShared here...
        }

        public static object Search(string param)
        {
            var window = new SearcherWindow();
            window.ShowDialog();

            return null;
        }
    }
}