TypeLoadException 说“没有实现”,但它已实现
-
09-09-2019 - |
题
我的测试机器上有一个非常奇怪的错误。错误是:
System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.
我就是不明白为什么。 SetShort
有没有在 DummyItem
类,我什至重新编译了一个版本,并写入事件日志,只是为了确保这不是部署/版本控制问题。奇怪的是调用代码甚至没有调用 SetShort
方法。
解决方案
笔记 - 如果这个答案对您没有帮助,请花点时间向下滚动浏览人们此后添加的其他答案。
简短回答
如果您将方法添加到一个程序集中的接口,然后添加到另一个程序集中的实现类,但您重建实现程序集而不引用新版本的接口程序集,则可能会发生这种情况。
在本例中,DummyItem 实现另一个程序集的接口。SetShort 方法最近被添加到界面和 DummyItem 中 - 但包含 DummyItem 的程序集是参考界面程序集的先前版本而重建的。因此,SetShort 方法实际上在那里,但没有将其链接到接口中的等效方法的魔法。
长答案
如果您想尝试重现此情况,请尝试以下操作:
创建类库项目:InterfaceDef,仅添加一个类,然后构建:
public interface IInterface { string GetString(string key); //short GetShort(string key); }
创建一个二级库项目:实现(使用单独的解决方案),将 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 }
创建第三个控制台项目:ClientCode,将两个dll复制到项目目录下,添加文件引用,在Main方法中添加如下代码:
IInterface test = new ImplementingClass(); string s = test.GetString("dummykey"); Console.WriteLine(s); Console.ReadKey();
运行代码一次,控制台显示“hello world”
取消注释两个 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 集并成功编译。
当我尝试在运行时实例化它们的接口类之一时,抛出了异常。我们确保所有其他参考文献都是最新的,但仍然没有运气。我们需要一段时间(使用对象浏览器)发现错误消息中方法的返回类型是来自新的、未引用的程序集的全新类型。
我们添加了对程序集的引用,错误就消失了。
- 该错误消息相当具有误导性,但或多或少指出了正确的方向(正确的方法,错误的消息)。
- 即使我们没有使用有问题的方法,也会发生异常。
- 这引出了我的问题:如果在任何情况下都会抛出此异常,为什么编译器不拾取它?
我在以下场景中收到此错误。
- 程序集 A 和 B 都引用了 System.Web.Mvc 版本 3.0.0.0
- 程序集 A 引用了程序集 B,并且具有实现程序集 B 接口的类以及从 System.Web.Mvc 返回类的方法。
- 程序集 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的exe引用任何CPU组件,这又引用的x86汇编引起的。
的异常抱怨上的类中MyApp.Implementations的方法(任何CPU),其衍生MyApp.Interfaces(任何CPU),但在fuslogvw.exe我发现了一个隐藏的“试图加载程序使用不正确的格式”从MyApp.CommonTypes(x86)的除外,它被两个。
我继续回来这... 这里的许多答案做解释什么问题但不知道如何解决它的一个伟大的工作。
这个解决方案是手动删除发布目录中的项目的bin文件。这将清理所有引用,并迫使该项目使用最新的DLL。
我不建议使用发布工具删除功能,因为这往往会甩开IIS。
我有另一个深奥溶液到该错误消息。我升级我的目标框架从.NET 4.0到4.6,我的单元测试项目是给我的“System.TypeLoadException ......没有一个实现”当我试图建立自己的错误。这也给了大致相同的所谓非执行的方法,上述第二个错误消息“‘BuildShadowTask’任务意外失败。”建议没有在这里似乎帮助,所以我搜索“BuildShadowTask”,发现的 MSDN上害得我使用文本编辑器删除从单元测试项目的csproj文件,这些行后。
<ItemGroup>
<Shadow Include="Test References\MyProject.accessor" />
</ItemGroup>
在此之后,这两个错误消失了,项目建成。
我在我使用Autofac和大量的动态组件加载的情况下遇到此错误。
当执行一个Autofac分辨率操作,运行时将无法加载组件中的一个。该错误消息抱怨Method 'MyMethod' in type 'MyType' from assembly 'ImplementationAssembly' does not have an implementation
。在Windows Server 2012 R2虚拟机上运行时出现症状,但做的不的出现在Windows 10或Windows Server 2016的虚拟机。
ImplementationAssembly
引用System.Collections.Immutable
37年1月1日,并且包含一个IMyInterface<T1,T2>
接口,将其在一个单独的DefinitionAssembly
限定的实施方式。 DefinitionAssembly
引用System.Collections.Immutable
1.1.36。
这IMyInterface<T1,T2>
这是“未实施”的方法有类型IImmutableDictionary<TKey, TRow>
,其在System.Collections.Immutable
定义的参数。
System.Collections.Immutable
程序中的目录中找到的实际拷贝为37年1月1日的版本。在我的Windows Server 2012 R2虚拟机,海关总署包含System.Collections.Immutable
1.1.36的副本。在Windows 10和Windows Server 2016年,GAC包含System.Collections.Immutable
37年1月1日的副本。当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>
我通过“钻石”形项目依赖项得到了这个:
- 项目 A 使用项目 B 和项目 D
- 项目 B 使用项目 D
我重新编译了项目A,但没有重新编译项目B,这使得项目B可以“注入”旧版本的项目D dll
我遇到这个时候我改名一个项目(和组件名称),将其通过一个ASP.NET项目他们依赖的。在Web项目类型在相关的组装实现的接口。尽管从生成菜单中执行清理解决方案,与以前的名字装配留在bin
文件夹,当我的web项目执行
var types = AppDomain.CurrentDomain.
GetAssemblies().
ToList().
SelectMany( s => s.GetTypes() /* exception thrown in this call */ )
;
以上异常被抛出,抱怨在实现Web类型的接口方法实际上没有实现。手动删除Web项目的bin
文件夹中的组件解决了这个问题。
我还当我的组件中的一个单元测试期间先前启用代码覆盖得到这个错误。出于某种原因,Visual Studio的“缓冲”老版这种特定的DLL,尽管我已经更新它来实现接口的新版本。禁用代码覆盖摆脱了错误的。
对于这种类型的问题,涉及管理C ++的另一种解释。
如果您尝试存根在组件中定义的接口创建使用具有特殊的签名被创建存根时,你会得到的异常托管C ++。
这是犀牛制品,可能使用任何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的有些模糊modopt
的犀牛制品邮寄列表。
也可以如果组件被使用Assembly.LoadFrom(字符串)加载导致此错误,并引用使用已加载的组件Assembly.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的解决方案,并开始从我的单元测试项目收到同样的异常。
检查所有的引用寻找旧文件,eventualy发现我需要做的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>
就我而言,它有助于重置 WinForms 工具箱。
我在打开时遇到异常 Form
在设计师中;但是,可以编译并运行代码,并且代码的行为符合预期。异常发生在本地 UserControl
从我引用的库之一实现一个接口。更新该库后出现该错误。
这 UserControl
已列在 WinForms 工具箱中。可能 Visual Studio 保留了对该库的过时版本的引用,或者在某处缓存了过时的版本。
以下是我从这种情况中恢复过来的方法:
- 右键单击 WinForms 工具箱,然后单击
Reset Toolbox
在上下文菜单中。 (这将从工具箱中删除自定义项目)。
就我而言,工具箱项目已恢复为默认状态;但是,工具箱中缺少指针箭头。 - 关闭视觉工作室。
在我的例子中,Visual Studio 因违规异常而终止并中止。 - 重新启动 Visual Studio。
现在一切都进展顺利。
FWIW,我这当是重定向到一个不存在的版本引用组件的配置文件。融合日志为赢!
我得到这个错误,因为我已经在其中是在该框架的4.5版本的组件“C”的一类,其中是在所述框架的4.5.1版本组件“A”实现接口和作为碱类组件“B”这也是在框架上的4.5.1版本。而试图加载程序集“B”系统抛出异常。此外,我已经安装了一些的NuGet包在所有这三个组件针对.NET 4.5.1。由于某些原因,即使的NuGet引用并没有在装配“B”表示,这是成功构建。
<强>原来,真正的问题是,组合件引用不同版本包含的接口和接口签名已更改版本之间一个NuGet包的强>
在我来说,我以前引用的一个兄弟文件夹中的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
文件夹中。任何旧的过时的组件是你的问题。
我遇到了几乎同样的问题。我正在摸不着头脑是什么导致了这个错误。我核对了一下,所有的方法都实现了。
在谷歌搜索上我得到了这个链接。根据 @Paul McLink 评论,这两个步骤解决了该问题。
- 重新启动 Visual Studio
- 清理、构建(重建)
和 错误消失了.
谢谢保罗:)
希望这可以帮助遇到此错误的人:)
我也遇到了这个问题,同时运行单元测试代码我。该应用程序运行良好,并没有任何错误。 在我的情况下,问题的原因是,我已经关闭了测试项目的建设。 重新启用我testprojects的建设解决了问题。
我看到这个在Visual Studio 2008专业版时,两个项目建成具有相同的名称,一个一类的lib SDF.dll,和一个引用汇编名sdf.exe的lib组件。 当我改变了参考组件的名称,异常走
这只是意味着该项目的实施是过时,我的案件。含的界面处的DLL被重建但实现DLL是陈旧。
下面是我拿到这个错误。
增加了一个extern
方法,但我的糊故障。所述DllImportAttribute
得到放在一个注释行。
/// <returns>(removed for brevity lol)</returns>[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
确保属性实际上是包含在源固定的问题。
我在WCF服务得到这个由于具有选择一个x86生成类型,从而使箱生活在仓\ 86,而不是箱。选择任何CPU造成重新编译的DLL去到正确的位置(我不会细谈,如何这发生在首位)。
我有同样的问题。我想通了,我的组装,这是由主程序加载,曾与“复制本地”一些参考设置为true。引用这些本地副本正在寻找在同一个文件夹以外的参考,这是不存在的,因为其他引用的“复制本地”设置为false。在“不小心”复制引用删除后,走了错误,因为主程序被设定为寻找引用的正确位置。显然,参考文献的本地副本拧向上调用,因为这些本地副本来替代存在于主节目的原有的序列。
在带回家的消息是出现这个错误,由于缺少的环节加载所需的组件。
在我的情况下,我试图使用TypeBuilder
创建类型。 TypeBuilder.CreateType
抛出该异常。我终于意识到我需要时调用MethodAttributes.Virtual
用于帮助的方法实现一个接口来TypeBuilder.DefineMethod
添加到属性。这是因为没有该标志,该方法没有实现接口,而是一种新的方法具有相同签名代替(即使没有指定MethodAttributes.NewSlot
)。
作为附录:当更新用于生成一个假货组件的NuGet包这也可能发生。假设你安装NuGet包的V1.0并创建一个假货大会“fakeLibrary.1.0.0.0.Fakes”。接下来,您更新到NuGet包的最新版本,说里面加入了新方法的接口V1.1。假货库仍在寻找库的V1.0。只需取下假装配和重新生成。如果是这样的问题,这可能会解决它。
我最近的窗口更新后接收此错误。我有一个服务类设置为从一个接口继承。该界面包含在返回的ValueTuple,在C#一种相当新的特征。一个签名
所有我可以猜到的是,Windows更新安装了一个新的,但即使明确引用它,更新绑定重定向,等...最终的结果却只是改变了方法的签名的东西“标准”我猜你可以说