在DLL中将DLL作为嵌入式资源包含在WPF项目中

时间:2011-06-23 17:51:09

标签: c# wpf dll include embed

我正在关注http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

我已将WPFToolkit.Extended.dll添加到我的解决方案中,并将其Build Action设置为Embedded Resource。

在App.OnStartup(StartupEventArgs e)中,我有以下代码:

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    String resourceName = "AssemblyLoadingAndReflection." + new AssemblyName(args.Name).Name + ".dll";
    String assemblyName = Assembly.GetExecutingAssembly().FullName;
    Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
    using (stream)
    {
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
    }
};

调试器会两次触发此代码块。

第一次:

resourceName is "AssemblyLoadingAndReflection.StatusUtil.resources.dll"
assemblyName is "StatusUtil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
stream is null

第二次:

resourceName is "AssemblyLoadingAndReflection.WPFToolkit.Extended.resources.dll"
assemblyName is "StatusUtil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
stream is null

代码在遇到stream.Length时抛出异常,因为它是null。

我不能使用ILMerge,因为它是一个WPF项目。

5 个答案:

答案 0 :(得分:7)

您必须将字符串"AssemblyLoadingAndReflection"更改为应用程序集的名称。

通过使用更多反射,您可以采取一些措施使此代码更通用:

Assembly.GetExecutingAssembly().FullName.Split(',').First()

别忘了附加一个圆点。如果dll不在应用程序集的资源中,这当然不起作用。

答案 1 :(得分:2)

H.B.的回答其实不太对劲。我们需要的前缀不是程序集的名称,而是项目的默认名称空间。这可能是不可能完全可靠的,但是下面的代码比假设它与程序集名称相同更可靠。

Assembly thisAssembly = Assembly.GetEntryAssembly();
String resourceName = string.Format("{0}.{1}.dll",
    thisAssembly.EntryPoint.DeclaringType.Namespace,
    new AssemblyName(args.Name).Name);

答案 2 :(得分:2)

内森菲利普的答案对我来说就像一个魅力......

这是对我有用的整个方法 (它也适用于多个dll)

public MainWindow()
    {
        InitializeComponent();

        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            Assembly thisAssembly = Assembly.GetEntryAssembly();
            String resourceName = string.Format("{0}.{1}.dll",
                thisAssembly.EntryPoint.DeclaringType.Namespace,
                new AssemblyName(args.Name).Name);

            using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
            {

                Byte[] assemblyData = new Byte[stream.Length];

                stream.Read(assemblyData, 0, assemblyData.Length);

                return Assembly.Load(assemblyData);

            }

        };
    }

答案 3 :(得分:0)

我尝试了上述所有答案,但它们对我不起作用。我找到了这篇文章,它就像一个魅力。

发布:http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application

我发现还需要编辑.csproj文件。这篇文章解释了如何做所有事情。

答案 4 :(得分:0)

我对如何在StackOverflow问题VB.NET embedded DLL in another DLL as embedded resource?

中动态加载嵌入式程序集有完整的解释