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

时间:2009-06-04 05:58:17

标签: c# .net fusion typeloadexception

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

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

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

41 个答案:

答案 0 :(得分:230)

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

简短回答

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

在这种情况下,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 :(得分:32)

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

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

答案 2 :(得分:22)

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

答案 3 :(得分:18)

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

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

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

  • 错误消息非常容易引起误解,但指向正确的方向(正确的方法,错误的消息)。
  • 即使我们没有使用相关方法,也会发生异常。
  • 这引出了我的问题:如果在任何情况下都抛出此异常,为什么编译器不能接收它?

答案 4 :(得分:16)

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

  • 程序集A和B都引用了System.Web.Mvc版本3.0.0.0
  • 程序集引用的程序集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。现在看来很明显!

感谢原创海报!

答案 5 :(得分:13)

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

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

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

  • C的构建引用了比现有版本更旧的程序集B

希望能帮到某人 - 我花了很多时间来解决这个问题。

答案 6 :(得分:9)

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

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

答案 7 :(得分:6)

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

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

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

答案 8 :(得分: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.Immutable 1.1.37,并包含IMyInterface<T1,T2>接口的实现,该接口在单独的DefinitionAssembly中定义。 DefinitionAssembly引用了System.Collections.Immutable 1.1.36。

来自IMyInterface<T1,T2>的&#34;未实施的方法&#34;具有IImmutableDictionary<TKey, TRow>类型的参数,其在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的不同版本,这意味着运行时没有考虑实现类来匹配接口定义。

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

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

答案 9 :(得分:6)

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

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

之后,两个错误都消失了,项目就建好了。

答案 10 :(得分:5)

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

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

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

答案 11 :(得分:5)

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

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

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

答案 12 :(得分:4)

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

答案 13 :(得分:3)

如果使用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;
}

答案 14 :(得分:3)

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

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

  1. 重新启动Visual Studio
  2. 清洁,构建(重建)
  3. 并且错误消失了

    Restart VS Plugin

    谢谢保罗:)

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

答案 15 :(得分:3)

在我的情况下,我之前在回复的一个兄弟文件夹中引用了一个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文件夹中的日期时间戳。任何旧的日期装配都是你的问题。

答案 16 :(得分:3)

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

答案 17 :(得分:3)

我收到了这个错误,因为我在集会中有一个班级&#39; C&#39;这是在框架的4.5版本上,在程序集中实现了一个接口&#39; A&#39;这是在框架的4.5.1版本上,并作为汇编&#39; B&#39;的基础类。这也是框架的4.5.1版本。系统在尝试加载程序集B&#39;时抛出了异常。另外,我在所有三个程序集上安装了一些针对.net 4.5.1的nuget包。出于某种原因,即使nuget引用未在程序集中显示,也正在构建成功。

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

答案 18 :(得分:3)

在我的情况下,它有助于重置WinForms工具箱。

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

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

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

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

答案 19 :(得分: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>

答案 20 :(得分: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#中)。导致问题as stated by Ayende Rahien on the Rhino Mocks mailing list的有点模糊modopt

答案 21 :(得分:2)

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

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

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

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

答案 22 :(得分:2)

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

答案 23 :(得分:2)

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

答案 24 :(得分:2)

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

答案 25 :(得分:1)

我今天收到此错误。我的问题是-不要在TFS中获取最新版本。在服务器上是带有接口的dll,其中一种方法已被修改。我使用一个旧的计算机-在我的PC中可以正常工作。解决方法:获取最新信息,重新构建

答案 26 :(得分:1)

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

所有我能猜到的是Windows更新安装了一个新的,但即使显式引用它,更新绑定重定向等...最终结果只是将方法的签名更改为“标准”我认为你可以说。

答案 27 :(得分:1)

当接口引用 3rd 方 dll (MWArray) 且“特定版本”设置为“True”而实现的类引用相同的 dll 但“特定版本”设置为“时,我发生了这种情况False',所以类和接口对同一个 dll 有不同的版本引用。

将两者都设置为“特定版本”:“假”或“真”(取决于您的需要)修复了它。

答案 28 :(得分:1)

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

答案 29 :(得分:1)

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

答案 30 :(得分:1)

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

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

答案 31 :(得分:1)

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

答案 32 :(得分:0)

为我解决问题的原因是CleanRebuild Solution

答案 33 :(得分:0)

只需添加我的经验即可,因为其他答案中没有涉及它:

在MsTest中运行单元测试时遇到了这个问题。

要测试的类在签名的程序集中。

该程序集的另一个版本恰好在GAC中(但具有相同的程序集版本号)。

强命名程序集的依赖关系解析算法与未签名的依赖关系算法略有不同,因为首先检查了GAC。

因此,MsTest正在选择GAC的程序集,而不是使用bin文件夹中的程序集,并尝试对其进行测试,这显然是行不通的。

解决方案是删除GAC的程序集。

请注意,对我来说,这是因为在运行测试时,这不是在构建服务器上发生的,因为该构建将使用新的程序集版本号编译该程序集。这意味着GAC中的程序集的较旧版本将不会被提取。

此外,如果您由于某种原因无法访问GAC,我在这里也找到了一种可能的解决方法:https://johanleino.wordpress.com/2014/02/20/workaround-for-unit-testing-code-that-reside-in-the-gac/

答案 34 :(得分:0)

我遇到了这个问题,只有我的本地机器出现了问题。我们小组中的其他开发人员和我的VM都没有问题。

最后,它似乎与“定位包”有关 Visual Studio 2017

  • 打开Visual Studio安装程序
  • 选择修改
  • 转到第二个顶部的“单个组件”标签
  • 查看您选择了哪些框架和目标包。
  • 我没有选择两个最新的定位包
  • 我还注意到我没有选择“高级ASP.NET功能”,而其他计算机则选择了
  • 选择并安装了新项目,一切都很好。

答案 35 :(得分:0)

还有另一种获取方式:

class GenericFoo<T> {}

class ConcreteFoo : GenericFoo<ClassFromAnotherAssembly> {}

未引用ClassFromAnotherAssembly的程序集中的代码。

var foo = new ConcreteFoo(); //kaboom

当ClassFromAnotherAssembly为ValueTuple时,这发生在我身上。

答案 36 :(得分:0)

通过更新Windows解决了我们的问题!我们的Web应用程序位于.Net 4.7.1和c#7.0上。当我们在不同的窗口中进行测试时,我们知道可以通过更新窗口来解决该问题。确实,在Windows 10(版本1703)和Windows Server 2012(去年未更新)中都出现了问题。更新它们两个之后,问题就解决了。实际上,asp.net次要版本(C:\ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319中的clr.dll版本的第三部分)在更新后有所更改。

答案 37 :(得分:0)

当我的集成测试项目试图加载一个不包含接口依赖关系解析的DLL时,我遇到了这个错误:

  1. 集成测试项目(引用主项目,但不引用 StructureMap)
  2. 主项目(引用StructureMap项目-用途 类构造函数中的接口)
  3. StructureMap项目(IoC-For()。Use();)

这导致抛出错误,因为找不到具体的实现。我在测试配置中排除了DLL,错误消失了

答案 38 :(得分:0)

对我来说,解决方案与以下事实有关:正在实施该接口的项目已设置了属性“ Register for COM Interop”。取消选中此选项可以为我解决问题。

答案 39 :(得分:0)

对我来说解决问题的是将以下内容添加到 ProjectReference 和/或 PackageReference 以及正在加载的程序集中的 <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>

这使我的项目文件看起来像这样:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  </PropertyGroup>

  <!-- For a package -->
  <ItemGroup>
    <PackageReference Include="SomePackage" Version="x.x.x.x">
      <Private>false</Private>
      <ExcludeAssets>runtime</ExcludeAssets>
    </PackageReference>
  </ItemGroup>

  <!-- For a project -->
  <ItemGroup>
    <ProjectReference Include="..\SomeProject\SomeProject.csproj">
      <Private>false</Private>
      <ExcludeAssets>runtime</ExcludeAssets>
    </ProjectReference>
  </ItemGroup>
</Project>

答案 40 :(得分:-1)

另一种可能性是依赖项中的发布和调试版本的混合。例如,程序集A依赖于程序集B,A是在调试模式下构建的,而GAC中的B副本是在发布模式下构建的,反之亦然。