类型是在未被引用的程序集中定义的,如何找出原因?

104

我知道这个错误信息很常见,SO上也有很多关于这个错误的问题,但是到目前为止没有任何解决方案能够帮助我,所以我决定发问。与大多数类似问题的不同之处在于我使用了App_Code目录。

错误信息:

CS0012: The type 'Project.Rights.OperationsProvider' is defined in an
assembly that is not referenced. You must add a reference to assembly
'Project.Rights, version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

源文件:

c:\inetpub\wwwroot\Test\Website\App_Code\Company\Project\BusinessLogic\Manager.cs

参照这里这里的建议,我已经删除了C:\Windows\Microsoft.NET/*.*内所有Project.Rights.dll的实例。根据这篇文章的内容,我检查了相关.cs文件的生成操作是否设置为“编译”,它们是这样设置的。我还仔细检查了包含“Project.Rights.OperationsProvider”类型的.cs文件是否部署到了App_Code目录中。

由于某种原因,应用程序没有在App_Code目录中查找该类型。由于我已经删除了我知道的所有Project.Rights.dll实例,我不知道错误消息所提到的程序集是哪个。


6
你正在使用一个类(假设为 A),该类公开了类型为 Project.Rights.OperationsProvider 的方法/属性/某个东西。编译器需要知道这是什么,然后会搜索该程序集(Project.Rights)。如果它找不到它(因为你的网站项目中没有对它的引用)...你就会得到这个错误。解决方案:不要从系统中删除该程序集!!! 添加对它的引用。 - Adriano Repetti
3
请尝试前往“工具-选项-项目和解决方案-生成和运行”,将两个详细度级别都设置为“详细”。这将告诉你哪些依赖项存在问题,以及编译器在哪里查找它们。 - danludwig
21个回答

111

当您遇到此错误时,往往并不明显出现了什么问题,但是正如错误提示的那样 - 您缺少一个引用。以以下代码行为例:

MyObjectType a = new MyObjectType("parameter");

看起来足够简单,而且您可能已经正确引用了"MyObjectType"。但是假设"MyObjectType"构造函数的某个重载需要一个您未引用的类型。例如,定义了一个重载如下:

public MyObjectType(TypeFromOtherAssembly parameter) {
    // ... normal constructor code ...
}

这至少是一个会导致产生错误的案例。因此,需要查找这种类型的模式,在该模式中引用了类型,但并未包含在该类型上调用函数时可能涉及的所有属性或方法参数类型。

希望这至少能让你朝着正确的方向前进!


19
关于扩展方法的注意事项:如果两个类具有相同名称的扩展方法,则来自一个类型的参数可以“感染”另一个类型的扩展方法的使用。 - Athari
@Athari 谢谢,我永远也想不到那个。 - Dave Cousineau
1
在寻找一段时间后,我偶然发现了这个答案。这正是我的问题,你的解释非常有帮助。非常感谢。 - Diane
4
如果我不想使用带有引用的构造函数,而是想使用其他不需要添加引用的构造函数,这该怎么办?看起来应该是可行的。 - Robert Iagar
1
这似乎非常奇怪,但我因为程序集名称大小写不匹配而遇到了此错误(看起来nuget是区分大小写的?)! 我有一个库C引用库B和A。库B还引用了库A,但使用名称“a”而不是“A”将A打包为依赖项。在构建库C时,我一直收到此错误,直到我纠正了B中依赖项的名称! - Tolu
@Athari 谢谢分享。我在这里遇到了完全相同的问题。两个不同程序集中具有相同名称的扩展方法,第一个(我正在使用的)有3个必需参数和2个可选参数(我没有传递),而另一个程序集上的扩展方法则有4个必需参数。当我立即开始传递第四个参数时,这个未知类型的第二个扩展方法就开始被测试(以找到最佳扩展),并且它破坏了构建。总之,我不得不添加对未知类型的引用,即使没有使用它。 - drizin

62

检查项目中的目标框架。

在我的情况下,“您必须向程序集添加引用”实际上意味着调用方和被引用的项目没有相同的目标框架。调用方项目使用了.Net 4.5,但是引用库的目标是4.6.1。

我相信,微软编译器可以更聪明地记录更有意义的错误消息。我已经向 https://github.com/dotnet/roslyn/issues/14756 提出了建议。


还要确保您了解框架类型之间的区别。它们以.NET开头,名称相似且版本号接近,但它们是不兼容的。请参考https://learn.microsoft.com/en-us/dotnet/standard/choosing-core-framework-server。 - Cale Sweeney

16

我的情况是因为进行了NuGet包更新,但只更新了解决方案中 某些 而非全部 项目对dll依赖项的引用 - 导致版本冲突。使用类Grep工具搜索解决方案中 *.csproj 文件内的文本,然后很容易找到需要更新的项目。


谢谢您的回答 - 我猜想它与此类似,但很高兴看到它。换句话说 - 我的父项目(服务)在我的数据层中调用了一个带有可选参数的构造函数,但该引用尚未添加到 .csproj 中。比较子级和父级 .csproj 文件应该会显示一个应该在父级中但不在其中的 ItemGroup。 - Ryanman
4
Visual Studio 的“程序包管理器”窗口是针对整个解决方案(而不是单个项目)的。其中有一个名为“Consolidate”的选项卡,它显示在不同项目中具有不同版本的程序包列表。使用它比使用类似于 grep 的工具更好。请注意,该翻译仅供参考,具体翻译应根据上下文和其他因素进行调整。 - Michael Freidgeim

11

当您出现此错误时,意味着您正在使用的代码引用了程序集中的某个类型,但该程序集不是项目的一部分,因此无法使用它。

删除Project.Rights.dll恰恰与您想要的相反。您需要确保您的项目可以引用该程序集。所以它必须放置在全局程序集缓存或者您的Web应用程序的~/Bin目录中。

如果您不想使用该程序集,则删除它也不是正确的解决方案。相反,您必须在代码中删除所有对它的引用。由于该程序集并非您编写的代码直接所需,而是由您正在引用的其他内容所需,因此您将不得不将该被引用的程序集替换为没有Project.Rights.dll作为依赖项的东西。


2
我不能使用汇编,这是一个要求。我需要摆脱它并将类存储在App_Code目录中。我知道它听起来怎么样,相信我。被指派修改应用程序以便所有业务逻辑都存储在App_Code而不是DLL中...这并不好玩。 - afaf12
1
不,这意味着他正在使用一个引用它的东西(而不是直接使用它)。@afaf12如果你必须摆脱它...你必须检查谁在使用它(将其想象为间接引用)。你不能简单地将代码粘贴到App_Code目录中,任何已编译的程序集仍将引用原始(和外部)程序集... - Adriano Repetti
我遇到了类似的问题,你的帖子帮了我很多。在我的情况下,我引用了一个名为"A"的程序集。这个程序集又使用了另一个程序集"B"。我一直收到一个错误,说程序集"B"丢失,尽管我已经将它添加到了我的项目中。一旦我将程序集"B"复制到我的bin目录中,问题就解决了。原因是我的项目没有使用程序集"B",但程序集"A"使用了它,找不到它,因此抛出了异常。谢谢。 - ykh

4
在我的情况下,我引用了一个正在构建的库,但是该库的平台/配置错误(我刚刚创建了该被引用的库)。
此外,我无法在Visual Studio配置管理器中解决问题--无法为此库切换和创建新的平台和配置。我通过更正项目的.sln文件中ProjectConfigurationPlatforms部分的条目来解决了这个问题。所有排列组合都设置为Debug | Any CPU(我不确定如何做到这一点)。我用工作项目的条目覆盖了损坏项目的条目,并更改了每个条目的GUID。
功能项目的条目:
{9E93345C-7A51-4E9A-ACB0-DAAB8F1A1267}.Release|x64.ActiveCfg = Release|x64 {9E93345C-7A51-4E9A-ACB0-DAAB8F1A1267}.Release|x64.Build.0 = Release|x64
损坏项目的条目:
{94562215-903C-47F3-BF64-8B90EF43FD27}.Release|x64.ActiveCfg = Debug|Any CPU {94562215-903C-47F3-BF64-8B90EF43FD27}.Release|x64.Build.0 = Debug|Any CPU
现在已修复损坏的条目:
{94562215-903C-47F3-BF64-8B90EF43FD27}.Release|x64.ActiveCfg = Release|x64 {94562215-903C-47F3-BF64-8B90EF43FD27}.Release|x64.Build.0 = Release|x64
希望这能帮助到某些人。

对我来说,情况很相似。Visual Studio 更改了一些我的项目的 GUIDs,从 FAE04EC0-301F-11D3-BF4B-00C04F79EFBC(C#)到 9A19103F-16F7-4668-BE54-9A1E7A4F7556(ASP.NET)。当我把它们改变回来之后,一切都恢复正常了。 - scor4er

3

我遇到了一个问题,不同的项目引用了同一个dll文件的不同版本。 我确保所有项目都引用了磁盘上相同的文件,错误就像我预期的那样消失了。


2
在Visual Studio中卸载和重新加载类库可以解决这个问题。

1
我在一个新创建的解决方案中遇到了这个问题,该解决方案使用了现有项目。由于某种原因,一个项目无法“看到”另一个项目,尽管它与其他所有项目具有相同的引用,并且被引用的项目也正在构建。我怀疑它未能检测到与多个目标框架有关的某些内容,因为它在一个框架中构建,但在另一个框架中没有构建成功。
清理和重建没有起作用,重新启动VS也没有起作用。
最终起作用的是打开“VS 2019的开发人员命令提示符”,然后发出msbuild MySolution.sln命令。这个命令成功完成后,VS也开始成功构建。

是的,事实证明这是唯一的解决方法。唯一的问题是,如果我需要调试我的解决方案,我必须在开发人员命令提示符中运行msbuild,然后在VS中按F5并选择最后一个成功的构建。 - Anthony

1

对我来说,这是由于项目直接或间接(通过另一个依赖项)引用了两个不同版本的Bouncy Castle构建,这些构建具有不同的程序集名称。其中一个Bouncy Castle构建是NuGet软件包,另一个是从GitHub下载的源代码的调试构建。两者名义上都是版本1.8.1,但GitHub代码的项目设置将程序集名称设置为BouncyCastle,而NuGet软件包则将程序集名称设置为BouncyCastle.Crypto。更改项目设置,使程序集名称对齐,解决了问题。


1
我建议您可以通过解释您是如何解决问题来使您的回答更有帮助。 - Stephen Kennedy

1

对于VS 2022,我关闭并重新打开它后问题得到了解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接