TypeLoadException表示“没有实现”,但它已实现

我的测试机器上有一个非常奇怪的错误。 错误是:

System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.

我只是无法理解为什么。 SetShort存在于DummyItem类中,我甚至重新编译了一个带有对事件日志的写入的版本,只是为了确保它不是部署/版本控制问题。 奇怪的是调用代码甚至不调用SetShort方法。

注意 – 如果此答案对您没有帮助,请花点时间向下滚动人们添加的其他答案。

简短的回答

如果将方法添加到一个程序集中的接口,然后添加到另一个程序集中的实现类,但是重新构建实现程序集而不引用新版本的接口程序集,则会发生这种情况。

在这种情况下,DummyItem实现来自另一个程序集的接口。 最近将SetShort方法添加到接口和DummyItem中 – 但是重新引用了包含DummyItem的程序集,引用了先前版本的接口程序集。 所以SetShort方法实际上就存在了,但没有魔术酱将它与接口中的等效方法联系起来。

答案很长

如果您想尝试重现此function,请尝试以下操作:

  1. 创建一个类库项目:InterfaceDef,只添加一个类,然后构建:

     public interface IInterface { string GetString(string key); //short GetShort(string key); } 
  2. 创建第二个类库项目:实现(使用单独的解决方案),将InterfaceDef.dll复制到项目目录并添加为文件引用,只添加一个类,并构建:

     public class ImplementingClass : IInterface { #region IInterface Members public string GetString(string key) { return "hello world"; } //public short GetShort(string key) //{ // return 1; //} #endregion } 
  3. 创建第三个控制台项目:ClientCode,将两个dll复制到项目目录中,添加文件引用,并将以下代码添加到Main方法中:

      IInterface test = new ImplementingClass(); string s = test.GetString("dummykey"); Console.WriteLine(s); Console.ReadKey(); 
  4. 运行代码一次,控制台说“你好世界”

  5. 取消注释两个dll项目中的代码并重建 – 将两个dll复制回ClientCode项目,重建并再次尝试运行。 尝试实例化ImplementingClass时发生TypeLoadException。

除了提问者自己的答案之外,还可能值得注意以下几点。 发生这种情况的原因是因为类可以使用与接口方法具有相同签名的方法而不实现该方法。 以下代码说明:

 public interface IFoo { void DoFoo(); } public class Foo : IFoo { public void DoFoo() { Console.WriteLine("This is _not_ the interface method."); } void IFoo.DoFoo() { Console.WriteLine("This _is_ the interface method."); } } Foo foo = new Foo(); foo.DoFoo(); // This calls the non-interface method IFoo foo2 = foo; foo2.DoFoo(); // This calls the interface method 

当我的应用程序没有引用定义错误消息中使用的方法的类的另一个程序集时,我得到了这个。 运行PEVerify会产生更多有用的错误:“系统无法找到指定的文件。”

我遇到了同样的消息,这是我们发现的:我们在项目中使用第三方dll。 在新版本发布之后,我们将项目更改为指向新的dll集并成功编译。

当我尝试在运行时设置其中一个接口类时抛出了exception。 我们确保所有其他参考文献都是最新的,但仍然没有运气。 我们需要一段时间来发现(使用对象浏览器)错误消息中方法的返回类型是来自新的未引用程序集的全新类型。

我们添加了对程序集的引用,错误消失了。

  • 错误消息非常误导,但或多或​​少指向正确的方向(正确的方法,错误的消息)。
  • 即使我们没有使用相关方法,也会出现例外情况。
  • 这引出了一个问题:如果在任何情况下都抛出此exception,为什么编译器不能解决它?

我在以下方案中收到此错误。

  • 程序集A和B都引用了System.Web.Mvc 3.0.0.0版
  • 程序集A引用了程序集B,并且具有使用从System.Web.Mvc返回类的方法实现程序集B的接口的类。
  • 程序集A已升级到System.Web.Mvc版本4.0.0.0
  • 程序集C运行下面的代码(FertPin.Classes.Contact包含在程序集A中):

var target = Assembly.GetAssembly(typeof(FertPin.Classes.Contact));

对我来说,修复程序是将程序集B中的System.Web.Mvc引用升级到4.0.0.0。 现在看来显而易见!

感谢原版海报!

另一方面,如果您的签名程序集版本不正确,则可能会出现此错误。 这不是这个原因的正常症状,但这是我得到它的情况

  • 一个asp.net项目包含程序集A和程序集B,B是强名称

  • 程序集A使用Activator.CreateInstance来加载程序集C(即没有引用单独构建的C)

  • 构建C引用了比当前存在的旧版本的程序集B.

希望能帮助别人 – 我花了很多时间来解决这个问题。

我也有这个错误,它是由任何CPU引用引用任何CPU程序集引起的x86程序集引起的。

exception抱怨MyApp.Implementations(Any CPU)中的一个类的方法,它派生了MyApp.Interfaces(Any CPU),但是在fuslogvw.exe中,我发现MyApp隐藏了“尝试加载程序格式不正确”的exception.CommonTypes(x86)由两者使用。

我得到了一个“钻石”形状的项目依赖:

  • 项目A使用项目B和项目D.
  • 项目B使用项目D.

我重新编译了项目A而不是项目B,它允许项目B“注入”旧版本的Project D dll

我在重命名项目(和程序集名称)时遇到了这个问题,这是一个ASP.NET项目所依赖的。 Web项目中的类型在依赖程序集中实现了接口。 尽管从Build菜单执行Clean Solution,但具有先前名称的程序集仍保留在bin文件夹中,并且当我的Web项目执行时

 var types = AppDomain.CurrentDomain. GetAssemblies(). ToList(). SelectMany( s => s.GetTypes() /* exception thrown in this call */ ) ; 

抛出上述exception,抱怨实现Web类型中的接口方法实际上没有实现。 手动删除Web项目的bin文件夹中的程序集解决了该问题。

我一直回到这里……这里的许多答案都很好地解释了问题所在而不是如何解决问题。

解决方案是手动删除项目发布目录中的bin文件。 它将清理所有引用并强制项目使用最新的DLL。

我不建议使用发布工具删除function,因为这往往会抛弃IIS。

我还有另一个深奥的解决方案来解决此错误消息。 我将目标框架从.Net 4.0升级到4.6,我的unit testing项目在我尝试构建时给了我“System.TypeLoadException …没有实现”错误。 它还提供了第二条错误消息,说明同一个未实现的方法,即“’BuildShadowTask’任务意外失败。” 这里没有任何建议似乎有帮助,所以我搜索了“BuildShadowTask”,并在MSDN上发现了一个post,这使我使用文本编辑器从unit testing项目的csproj文件中删除这些行。

    

在那之后,两个错误消失了,项目建成了。

我在使用Autofac和大量动态程序集加载的上下文中遇到此错误。

执行Autofac解析操作时,运行时将无法加载其中一个程序集。 错误消息抱怨Method 'MyMethod' in type 'MyType' from assembly 'ImplementationAssembly' does not have an implementation 。 在Windows Server 2012 R2 VM上运行时出现症状,但在Windows 10或Windows Server 2016 VM上出现这些症状。

ImplementationAssembly引用了System.Collections.Immutable 1.1.37,并包含了一个IMyInterface IMyInterface接口的实现,它是在一个单独的DefinitionAssemblyDefinitionAssembly引用了System.Collections.Immutable 1.1.36。

来自IMyInterface的“未实现”的方法具有类型为IImmutableDictionary ,其在System.Collections.Immutable定义。

在程序目录中找到的System.Collections.Immutable的实际副本是版本1.1.37。 在我的Windows Server 2012 R2 VM上,GAC包含System.Collections.Immutable 1.1.36的副本。 在Windows 10和Windows Server 2016上,GAC包含System.Collections.Immutable 1.1.37的副本。 仅当GAC包含较旧版本的DLL时才会发生加载错误。

因此,程序集加载失败的根本原因是对System.Collections.Immutable的不匹配引用。 接口定义和实现具有相同的方法签名,但实际上依赖于不同版本的System.Collections.Immutable ,这意味着运行时没有考虑实现类来匹配接口定义。

将以下绑定重定向添加到我的应用程序配置文件中修复了此问题:

     

当我之前在其中一个程序集的unit testing期间启用了代码覆盖率时,我也遇到了这个错误。 由于某种原因,Visual Studio“缓冲”了这个特定DLL的旧版本,即使我已经更新它以实现新版本的接口。 禁用代码覆盖率可以消除错误。

针对托管C ++的此类问题的另一种解释。

如果您尝试存根使用具有特殊签名的托管C ++创建的程序集中定义的接口,则在创建存根时将获得exception。

对于Rhino Mocks以及可能使用System.Reflection.Emit任何模拟框架都是如此。

 public interface class IFoo { void F(long bar); }; public ref class Foo : public IFoo { public: virtual void F(long bar) { ... } }; 

接口定义获得以下签名:

 void F(System.Int32 modopt(IsLong) bar) 

请注意,C ++类型long映射到System.Int32 (或简称为C#中的int )。 正如Ayende Rahien在Rhino Mocks邮件列表中所述,引起问题的是一些模糊的modopt

如果使用Assembly.LoadFrom(String)加载程序集并引用已使用Assembly.Load(Byte [])加载的程序集,也可能导致此错误。

例如,您已将主应用程序引用的程序集嵌入为资源,但您的应用程序从特定文件夹加载插件。

应该使用Load,而不是使用LoadFrom。 以下代码将完成这项工作:

 private static Assembly LoadAssemblyFromFile( String filePath ) { using( Stream stream = File.OpenRead( filePath ) ) { if( !ReferenceEquals( stream, null ) ) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read( assemblyData, 0, assemblyData.Length ); return Assembly.Load( assemblyData ); } } return null; } 

我刚刚将一个解决方案从MVC3升级到MVC5,并开始从我的Unit测试项目中收到相同的exception。

检查了所有寻找旧文件的引用,最终发现我需要在我的unit testing项目中为Mvc做一些bindingRedirects。

                    

在我的例子中,它有助于重置WinForms工具箱。

在设计师中打开Form时我得到了例外; 但是,编译和运行代码是可能的,并且代码按预期运行。 在我的一个引用库中实现接口的本地UserControl发生exception。 此库更新后出现错误。

UserControl列在WinForms工具箱中。 可能Visual Studio保留了对库的过时版本的引用,或者在某处缓存了过时的版本。

以下是我从这种情况中恢复的方式:

  1. 右键单击WinForms工具箱,然后单击上下文菜单中的“ Reset Toolbox ”。 (这会从工具箱中删除自定义项目)。
    在我的例子中,工具箱项目已恢复到默认状态; 但是,工具箱中缺少指针箭头。
  2. 关闭Visual Studio。
    在我的情况下,Visual Studio以违规exception终止并中止。
  3. 重新启动Visual Studio。
    现在一切顺利。

FWIW,当有一个配置文件重定向到一个不存在的引用程序集版本时,我得到了这个。 融合日志获胜!

我得到了这个错误,因为我在一个程序集’C’中有一个类,它在框架的4.5版本上,在程序集’A’中实现了一个接口,它在框架的4.5.1版本上,并作为程序集的基类’B’也在框架的4.5.1版本上。 系统在尝试加载程序集“B”时抛出了exception。 另外,我在所有三个程序集上安装了一些针对.net 4.5.1的nuget包。 出于某种原因,即使nuget引用未在程序集“B”中显示,它也正在成功构建。

事实certificate,真正的问题是程序集引用了包含接口的nuget包的不同版本,并且接口签名在版本之间发生了变化。

在我的情况下,我之前在repo之外的兄弟文件夹中引用了一个mylib项目 – 让我们调用v1.0

 |-- myrepo | |-- consoleApp | |-- submodules | |-- mylib (submoduled v2.0) |-- mylib (stale v1.0) 

后来我做得很好并通过git子模块使用它 – 让我们调用v2.0 。 但是,一个项目consoleApp未正确更新。 它仍然引用我的git项目之外的旧v1.0项目。

令人困惑的是 ,即使*.csproj明显错误并且指向v1.0 ,Visual Studio IDE也将路径显示为v2.0项目! F12检查接口和类也转到了v2.0版本。

编译器放入bin文件夹的程序集是v1.0版本,因此很头疼。

IDE对我说谎的事实使得实现错误变得更加困难。

解决方案 :从ConsoleApp删除项目引用并对其进行重新读取。

一般提示:从头开始重新编译所有程序集(如果可能,当然不能用于nuget包)并检查bin\debug文件夹中的日期时间戳。 任何旧的日期assembly都是你的问题。

我遇到了几乎同样的问题。 是什么导致了这个错误。 我交叉检查,所有方法都实现了。

谷歌搜索我得到了这个链接。 基于@Paul McLink评论,这两个步骤解决了这个问题。

  1. 重新启动Visual Studio
  2. 清洁,建造(重建)

并且错误消失了

重启VS插件

谢谢保罗:)

希望这可以帮助遇到此错误的人:)

我在运行我的unit testing时遇到了这个问题。 应用程序运行正常,没有错误。 我的问题的原因是我关闭了测试项目的建设。 重新启用我的测试项目的构建解决了这些问题。

我在Visual Studio Pro 2008中看到这个,当时有两个项目构建了具有相同名称的程序集,一个是lib SDF.dll类,另一个是使用程序集名称sdf.exe引用lib的。 当我更改引用程序集的名称时,exception消失了

这是我对这个错误的看法。

添加了一个extern方法,但我的粘贴有问题。 DllImportAttribute被放在注释掉的行上。

 /// (removed for brevity lol)[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWindowVisible(IntPtr hWnd); 

确保该属性实际包含在源中修复了该问题。

我在WCF服务中得到了这个,因为选择了x86构建类型,导致bisn生活在bin \ x86而不是bin下。 选择任何CPU导致重新编译的DLL转到正确的位置(我不会详细说明首先如何发生这种情况)。

这只是意味着我的情况下实施项目已经过时了。 包含接口的DLL已重建,但实现dll已过时。

我有同样的问题。 我发现我的程序集由主程序加载,其中一些引用的“Copy Local”设置为true。 这些引用的本地副本在同一文件夹中查找其他引用,这些引用不存在,因为其他引用的“Copy Local”设置为false。 删除“意外”复制的引用后,错误消失了,因为主程序设置为查找引用的正确位置。 显然,参考文献的本地副本搞砸了调用顺序,因为使用了这些本地副本而不是主程序中存在的原始副本。

回车消息是由于缺少加载所需组件的链接而出现此错误。

就我而言,我试图使用TypeBuilder来创建一个类型。 TypeBuilder.CreateType引发了此exception。 我最终意识到,在为有助于实现接口的方法调用TypeBuilder.DefineMethod时,我需要将MethodAttributes.Virtual添加到属性中。 这是因为没有此标志,该方法不实现接口,而是实现具有相同签名的新方法(即使不指定MethodAttributes.NewSlot )。

作为附录:如果更新用于生成伪assembly的nuget包,也会发生这种情况。 假设您安装了一个nuget包的V1.0并创建了一个假货组件“fakeLibrary.1.0.0.0.Fakes”。 接下来,您将更新到nuget软件包的最新版本,例如v1.1,它为接口添加了一个新方法。 Fakes库仍在寻找库的v1.0。 只需取下假assembly件并重新生成即可。 如果这是问题,这可能会解决它。

最近的Windows更新后我收到此错误。 我有一个服务类设置为从接口inheritance。 该接口包含一个返回ValueTuple的签名,这是C#中一个相当新的特性。

所有我能猜到的是Windows更新安装了一个新的,但甚至明确地引用它,更新绑定重定向等…最终的结果只是将方法的签名更改为“标准”,我想你可以说。