TypeLoadException表示"没有实现",但它已实现

Ben*_*jol 263 .net c# typeloadexception fusion

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

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

我只是无法理解为什么.SetShort是否在DummyItem课堂上,我甚至重新编译了一个带有写入事件日志的版本,以确保它不是部署/版本问题.奇怪的是调用代码甚至不调用该SetShort方法.

Ben*_*jol 237

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

简短的回答

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

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

答案很长

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

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

    public interface IInterface
    {
        string GetString(string key);
        //short GetShort(string key);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 创建第三个控制台项目:ClientCode,将两个dll复制到项目目录中,添加文件引用,并将以下代码添加到Main方法中:

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

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

  • 解决方案是手动删除bin文件.发布不会将它们视为已更改,因此您需要强制它具有最新版本.这应该在最受好评的答案中注意到! (12认同)
  • 嗯,看起来微软的错误信息中有一个错误 - 它说的是一个类"DummyItem"的方法没有实现,这显然是假的....真正的问题是接口的方法是没有的由DummyItem实现. (4认同)
  • 有什么好的最终解决方案吗?微软推荐什么解决方案? (3认同)

Tim*_*mwi 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
Run Code Online (Sandbox Code Playgroud)


sil*_*one 22

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


Ben*_*Ben 19

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

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

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

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


Dam*_*yer 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.现在看来显而易见!

感谢原版海报!


小智 13

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

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

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

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

希望对某人有所帮助 - 我花了很多时间来解决这个问题.


Ric*_*all 9

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

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


DJ.*_*DJ. 6

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

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

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


Ton*_*kas 6

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

<ItemGroup>
  <Shadow Include="Test References\MyProject.accessor" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

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


Hyd*_*rum 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>接口的实现,它是在一个单独的定义中定义的DefinitionAssembly.DefinitionAssembly参考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>
Run Code Online (Sandbox Code Playgroud)


小智 5

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

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

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

  • 是的,我喜欢将其视为[雷诺](http://images.google.com/images?q=renault+logo)问题 (16认同)

G-W*_*Wiz 5

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

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

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