TypeLoadException表示“未实现”,但已实现


270

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

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

我只是不明白为什么。SetShort有没有在DummyItem班级,我甚至已经重新编译版本写入到事件日志,只是为了确保它不是一个部署/版本问题。奇怪的是,调用代码甚至没有调用该SetShort方法。


15
我喜欢您如何与社区分享您的经验来帮助我们所有人,甚至鼓励我们也阅读其他答案,谢谢。可悲的是,没有任何建议对我有用。想知道最终为我工作的是什么?重新启动Visual Studio。为什么我不先尝试呢?
Paul McLean 2014年

谢谢Paul,在阅读您的评论后,我先尝试了一个。像魅力一样工作:-)
2014年

感谢保罗,为我节省了几个小时,不停地像猴子一样挠挠我的头……
朱健恩

此外,在VS 2017 15.7更新之后,VS会告诉您重新启动。您可能没有这样做(像我一样,因为我忘记了开会)。我喜欢这些误差修改的craploads ...
Structed

只是添加我的2p-在MsTest中运行单元测试时遇到了这个问题。测试中的类在已签名的程序集中。该程序集的另一个版本恰好在GAC中。MsTest正在选择GAC的程序集,而不是使用bin文件夹中的程序集,并试图对其进行测试,这显然是行不通的。解决方案是删除GAC的程序集
tom redfern

Answers:


244

注意 -如果此答案对您没有帮助,请花一些时间向下滚动人们在此之后添加的其他答案。

简短答案

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

在这种情况下,DummyItem实现了另一个程序集的接口。SetShort方法最近已添加到接口和DummyItem中-但是包含DummyItem的程序集是根据接口程序集的先前版本重建的。因此,SetShort方法有效地存在于其中,但没有魔术酱将其链接到界面中的等效方法。

长答案

如果要尝试重现此内容,请尝试以下操作:

  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. 运行一次代码,控制台显示“ hello world”

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


1
您可能需要添加控制台应用程序,应使用新的DLL作为参考来重建。仅复制DLL将不起作用,这可能是由于版本不匹配(例如,在编译源DLL之后版本会更改)。那是公平的理解吗?
shahkalpesh

@shahkalpesh好点-对我来说,F5再次“奔跑”。我已经更新了答案。当然,使用像样的源代码控制工具不会发生所有这些事情,但不要让我着手研究这个问题……
Benjol 2009年

4
嗯,看来Microsoft的错误消息中有错误-就是说“ DummyItem”类的方法没有实现,这显然是错误的……。真正的问题是接口的方法不是不是由DummyItem实现的。
Qwertie 2010年

3
有什么好的最终解决方案吗?微软推荐什么解决方案?
Kiquenet 2012年

12
解决方法是手动删除bin文件。该发布不会将其视为已更改,因此您需要强制其具有最新信息。这确实应该在评分最高的答案中注明!
DJ。

33

除了已经提出的问询者自己的答案之外,还应注意以下几点。发生这种情况的原因是,一个类可能具有与接口方法具有相同签名的方法,而无需实现该方法。以下代码说明了这一点:

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

这就为我解决了这个问题,它所声称的方法缺少的混淆级别是在父类实现的接口中声明的,并在子类中再次声明。从子类中删除重复项可以使错误消失。
ilikeprogramming

22

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


19

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

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

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

  • 该错误消息颇具误导性,但或多或​​少指向正确的方向(正确的方法,错误的消息)。
  • 即使我们没有使用有问题的方法,也会发生异常。
  • 这就引出了一个问题:如果在任何情况下都抛出此异常,为什么编译器不选择它?

17

在以下情况下,我收到此错误。

  • 程序集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。现在看来很明显!

多亏了原始海报!


我有类似的东西,但版本却相反。以.NET 2为目标的一种方法从v.2的System.Windows.Forms返回一种类型。在以.NET 4为目标的程序集中,其重写的实现返回的是相同类型,但来自System.Windows.Forms v4。它编译良好,但是ReflectionOnlyLoadFrom不喜欢它。
史蒂芬·休利特

我有一个类似的问题,这是由于将面向.NET2的类型加载到.NET4应用程序的ReflectionOnly上下文中引起的。我通过将.NET2核心程序集的所有程序集请求重定向到AppDomain.ReflectionOnlyAssemblyResolve事件中的.NET4对应项来解决此问题。
Chaquotay

这是我的问题:)谢谢!
安托万·埃伦科夫

13

其他时间,如果签名版的版本不正确,则会出现此错误。这不是此原因的正常症状,但这是我得到的情况

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

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

  • 生成的C引用的程序集B的版本高于当前版本

希望能对某人有所帮助-我花了很长时间才弄清楚这一点。


9

我也有此错误,它是由引用任何CPU程序集的Any CPU exe引起的,而该程序集又引用了x86程序集。

该异常抱怨MyApp.Implementations(任何CPU)中的类上的方法派生了MyApp.Interfaces(任何CPU),但是在fuslogvw.exe中,我从MyApp中发现了一个隐藏的“试图以错误的格式加载程序”异常两者都使用.CommonTypes(x86)。


6

我继续回到这个问题上。这里的许多答案都很好地解释了问题所在,而不是解决方法。

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

我不建议使用发布工具“删除”功能,因为这往往会使IIS失效。


我发现在非Web项目中也是这种情况-我在另一个程序集中反映了一个程序集(使用LoadFile),清理和重建均不起作用-从两个项目的bin文件夹中删除所有文件都有效。为建议加油!
d219

由于该特定项目在本地使用IIS,因此我也必须进行IIS重置。
蒂姆·威尔逊

6

对于此错误消息,我还有另一个深奥的解决方案。我将目标框架从.Net 4.0升级到4.6,并且我的单元测试项目在尝试构建时给了“ System.TypeLoadException ...没有实现”错误。它还给出了另一个错误消息,该错误消息涉及相同的据称未实现的方法,该方法指出“'BuildShadowTask'任务意外失败。” 这里的建议似乎都没有帮助,因此我搜索了“ BuildShadowTask”,并在MSDN上找到了一篇帖子,帖子使我使用文本编辑器从单元测试项目的csproj文件中删除了这些行。

<ItemGroup>
  <Shadow Include="Test References\MyProject.accessor" />
</ItemGroup>

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


这就是我的答案。从.NET 4.5升级到4.6后,我遇到了此错误。
twblamer

6

我在使用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.Immutable1.1.37,并包含IMyInterface<T1,T2>接口的实现,该接口的定义在单独的中DefinitionAssemblyDefinitionAssembly参考System.Collections.Immutable1.1.36。

IMyInterface<T1,T2>“未实现” 的方法的参数类型为IImmutableDictionary<TKey, TRow>,在中定义System.Collections.Immutable

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

因此,组装加载失败的根本原因是对的不匹配引用System.Collections.Immutable。接口定义和实现具有外观相同的方法签名,但实际上取决于的不同版本System.Collections.Immutable,这意味着运行时不会考虑实现类与接口定义匹配。

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

<dependentAssembly>
        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.1.37.0" newVersion="1.1.37.0" />
</dependentAssembly>

我可以问你如何找到它吗?您是否使用了任何非标准的调试技术?我遇到相同的错误,但我认为这是由不同的dll引起的,因为我已经为不可变对象设置了绑定重定向。
t3chb0t

1
嗯 前一阵子 我认为主要线索是“未实现”方法的参数使用的类型System.Collections.Immutable。就我而言,受影响的方法中没有很多其他候选参数或返回类型。我还记得使用ILSpy检查已编译的“ DefinitionAssembly”和“ ImplementationAssembly” DLL中的依赖项元数据,特别是查看引用的版本。
Hydrargyrum

1
非常感谢!;-)我安装了Visual Studio的ILSpy扩展,并查看了References分支,该System.Net.Http包中有一个,我dependentAssembly为其添加了元素,并从ILSpy复制了信息,它现在可以正常工作,错误消失了!
t3chb0t

我通过将其放入代码中并在其后放置一个断点以查看值并看到加载了两个版本的System.Net.Http来找出哪个是差的GAC程序集:var loadAssemblies =来自AppDomain.CurrentDomain中的。通过a.FullName选择(a.FullName,a)的GetAssemblies()顺序;
paulie4 '18

5

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

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

我重新编译了项目A,但没有重新编译项目B,这使项目B可以“注入”项目D dll的旧版本。


16
是的,我想将其视为雷诺问题
Benjol 2010年

我想我也有类似的问题,只是在两个项目之间。我手动编译了新的。之后,它工作顺利。
Departamento B

5

当我重命名ASP.NET项目依赖的项目(和程序集名称)时,我遇到了这个问题。Web项目中实现的类型在从属程序集中实现的接口。尽管从“生成”菜单执行“清洁解决方案”,但具有先前名称的程序集仍保留在bin文件夹中,并且在我的Web项目执行时

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

抛出上述异常,抱怨实现的Web类型中的接口方法未实际实现。手动删除Web项目bin文件夹中的程序集即可解决此问题。


4

当我先前在其中一个程序集的单元测试期间启用代码覆盖率时,我也遇到了此错误。由于某种原因,即使我已更新Visual Studio以实现接口的新版本,Visual Studio仍“缓冲”了该特定DLL的旧版本。禁用代码覆盖率摆脱了该错误。


4

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

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

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

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;
}

3

关于托管C ++这类问题的另一种解释。

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

这对于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(或仅int在C#中)。正如Rhino Mocks邮件列表上的Ayende Rahien所说的,modopt这是造成问题的原因有些晦涩 。


使用数据类型时出现此错误System::Byte。我更改了签名以接受,unsigned short然后天空又变成了蓝色。
克里希特

3

我刚刚将解决方案从MVC3升级到MVC5,并开始从我的单元测试项目中收到相同的异常。

检查所有引用以查找旧文件,最终发现我需要在单元测试项目中为Mvc做一些bindingRedirects。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

3

就我而言,它有助于重置WinForms工具箱。

Form在设计器中打开a时出现异常;但是,可以编译和运行代码,并且代码的行为符合预期。异常发生在本地UserControl实现了我引用的库之一的接口。更新该库后出现错误。

这个 UserControl被列入的WinForms工具箱。可能是Visual Studio在库的过时版本上保留了引用,或者在某个地方缓存了过时的版本。

这是我从这种情况中恢复过来的方法:

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

3

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


3

我收到此错误的原因是,我在框架“ 4.5”的程序集“ C”中有一个类,在框架“ 4.5.1”的程序集“ A”中实现了一个接口,并充当了程序集的基类框架的版本4.5.1中的“ B”。尝试加载程序集“ B”时,系统引发了异常。另外,我在所有三个程序集中都安装了一些针对.net 4.5.1的nuget软件包。由于某些原因,即使在程序集“ B”中未显示nuget引用,它也已成功构建。

原来,真正的问题是程序集引用了包含接口的nuget包的不同版本,并且接口签名在两个版本之间已更改。


3

就我而言,我以前mylib在存储库之外的同级文件夹中引用了一个项目,我们称其为v1.0

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

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

令人困惑的是,即使*.csproj显然是错误的并且指向v1.0,Visual Studio IDE还是将路径显示为v2.0项目!F12检查界面和类去了v2.0版本。

v1.0版本由编译器放入bin文件夹中,因此很麻烦。

IDE对我撒谎这一事实使发现该错误变得异常困难。

解决方案:从中删除项目引用ConsoleApp并重新阅读它们。

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


3

我面临几乎相同的问题。我挠头是什么导致此错误。我交叉检查,所有方法均已实施。

在谷歌搜索中,我获得了其他链接。基于@Paul McLink的评论,这两个步骤解决了该问题。

  1. 重新启动Visual Studio
  2. 清理,构建(重建)

错误了

重新启动VS插件

谢谢保罗:)

希望这对遇到此错误的人有所帮助:)


2

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


2

我在Visual Studio Pro 2008中看到了这一点,当时两个项目用相同的名称构建了程序集,一个用类lib SDF.dll命名,而一个用程序集名称sdf.exe引用了lib的程序集。当我更改引用程序集的名称时,异常消失了


2

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


2

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

添加了一种extern方法,但是我的粘贴有问题。在DllImportAttribute得到了穿上注释掉线。

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

确保该属性实际上已包含在源中,从而解决了该问题。


2

由于选择了x86构建类型,因此在WCF服务中得到了此信息,这导致垃圾箱位于bin \ x86而不是bin下。选择“任何CPU”会导致重新编译的DLL进入正确的位置(我不会详细介绍这种情况是如何发生的)。


1

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

带回家的消息是由于缺少链接以加载所需的程序集而出现此错误。


1

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


1

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


1

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

我所能猜测的是,Windows Update安装了一个新的,但甚至明确引用了它,更新了绑定重定向等。最终结果只是将方法的签名更改为某种“标准”的名称,我猜您可能会说。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.