【问题标题】:Class library loses references (dlls) when being used类库在使用时会丢失引用(dll)
【发布时间】:2016-05-16 14:16:36
【问题描述】:

抱歉标题。我不知道如何简短地描述这个问题。 我的问题是我有一个class-library,其中有references to other (third party) DLLs。 我需要在另一个项目中使用这个类库,所以我显然将我的类库的 .dll 添加到我的主项目中。

当我启动我的主项目时,总是出现一个错误,提示在我的类库中找不到引用 (dll)。

如果我将整个类库作为项目添加到我在 Visual Studio 中的 projectmap 中,然后引用整个项目,则不会发生此错误。

我真的不想将整个类库作为一个项目添加到我制作的每个“宿主”项目中。

有谁知道为什么在添加类库的 .dll 时会出现此错误,但在添加类库的整个项目作为参考时却没有?

即使我没有添加整个库项目作为参考,也必须有解决方案才能使其正常工作。不然做个类库就没有意义了吧?

顺便说一句:我的类库包含第三方dll,并且第三方dll的本地副本属性设置为true。

提前致谢!

编辑: 我的目标是真正使类库可移植,即使它包含第三方库。我只想将 .dll 提供给另一台电脑并使用它,而不是每次都添加整个类库项目。

【问题讨论】:

    标签: c# dll reference assemblies class-library


    【解决方案1】:

    错误是因为您没有在第二个项目中复制 dll,您添加了对 dll 的引用,因此它被复制了,但不是您的 dll 引用的 dll,因此缺少库。

    或者您使用您的 dll 重新分发依赖项,或者您可以将 dll 作为资源嵌入到您的 dll 中,然后拦截程序集负载并通过资源提供它:http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

    编辑:为了在 dll 中执行此操作,您需要使用静态类并在使用任何依赖于其他库的类之前调用​​静态初始化程序。

    这是一个示例设置:

    -一个名为 LibraryB 的库,它提供了一个像这样的简单类:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace LibraryB
    {
        public class ReferencedClass
        {
            public int GetIt()
            {
    
                return 5;
    
            }
        }
    }
    

    -一个名为 LibraryA 的库,它引用 LibraryB 并提供两个类,初始化器和真实类:

    初始化器

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace LibraryA
    {
        public static class Initializer
        {
            public static void Init()
            {
                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
                {
    
                    if (!args.Name.StartsWith("LibraryB"))
                        return null;
    
                    return Assembly.Load(LibraryA.Properties.Resources.LibraryB);
    
                }; 
            }
        }
    }
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace LibraryA
    {
        public class RealClass
        {
            public int DoIt()
            {
    
                LibraryB.ReferencedClass cl = new LibraryB.ReferencedClass();
                return cl.GetIt();
    
            }
        }
    }
    

    LibraryA 还具有作为资源嵌入的 LibraryB.dll 编译库。

    -一个名为 Test 的项目,它只引用 LibraryA:

    using LibraryA;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Initializer.Init();
                RealClass c = new RealClass();
                Console.WriteLine("From LibraryA: " + c.DoIt());
                Console.ReadKey();
            }
        }
    }
    

    如果您设置了所有内容并执行它,它将起作用,请记住,如果您是通过 Visual Studio 进行的,vs 将复制 dll,以便在编译所有复制 exe 和 LibraryA 并执行后进行真正的测试,它可以在没有 LibraryB 的情况下工作,并且 LibraryB 正在从 LibraryA 使用。

    【讨论】:

    • 他提到这适用于可执行文件 (.exe)。这也适用于.dll吗?我以前从来没有这样做过,也没有听说过任何关于它的事情。谢谢顺便说一句。这似乎是解决这个问题的正确开始。
    • 应该,但我不是 100% 安全的,最好的方法是测试
    • 我有,但是好像已经有问题了。我不能在“程序”初始化时调用它,因为甚至没有开始类(main)也没有构造函数。
    • 这应该没问题,创建一个带有名为“Init()”的静态函数的静态类,在该函数中挂钩事件。想要使用您的 dll 的用户应该首先调用该函数,然后库应该可用。让我检查一下是否有效,如果有效,我将扩大答案
    • 它有效,给我5分钟,我会写一个例子。
    猜你喜欢
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多