我们的测试机器上有个很奇怪的bug。错误是:

系统。来自程序集“activeviewer(…)”的类型“DummyItem”中的方法“SetShort”没有实现。

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


当前回答

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

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

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

其他回答

这类问题的另一种解释涉及托管c++。

如果您试图存根使用托管c++创建的具有特殊签名的程序集中定义的接口,您将在创建存根时得到异常。

对于Rhino mock和任何使用System.Reflection.Emit的mock框架都是如此。

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导致的问题。

在我的例子中,我试图使用TypeBuilder创建一个类型。TypeBuilder。CreateType抛出此异常。我最终意识到我需要添加MethodAttributes。在调用TypeBuilder时,将属性虚拟化。帮助实现接口的方法的DefineMethod。这是因为如果没有这个标志,该方法不会实现接口,而是实现一个具有相同签名的新方法(甚至没有指定MethodAttributes.NewSlot)。

为我解决的问题是添加以下到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>

注:如果这个答案对你没有帮助,请花点时间向下滚动人们添加的其他答案。

简短的回答

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

在本例中,DummyItem实现了来自另一个程序集的接口。SetShort方法最近被添加到接口和DummyItem中—但是包含DummyItem的程序集是引用先前版本的接口程序集重新构建的。因此SetShort方法有效地存在,但没有将其链接到接口中的等效方法。

长回答

如果你想尝试复制这个,试试下面的方法:

Create a class library project: InterfaceDef, add just one class, and build: public interface IInterface { string GetString(string key); //short GetShort(string key); } Create a second class library project: Implementation (with separate solution), copy InterfaceDef.dll into project directory and add as file reference, add just one class, and build: public class ImplementingClass : IInterface { #region IInterface Members public string GetString(string key) { return "hello world"; } //public short GetShort(string key) //{ // return 1; //} #endregion } Create a third, console project: ClientCode, copy the two dlls into the project directory, add file references, and add the following code into the Main method: IInterface test = new ImplementingClass(); string s = test.GetString("dummykey"); Console.WriteLine(s); Console.ReadKey(); Run the code once, the console says "hello world" Uncomment the code in the two dll projects and rebuild - copy the two dlls back into the ClientCode project, rebuild and try running again. TypeLoadException occurs when trying to instantiate the ImplementingClass.

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

集成测试项目(参考主项目,但不是 StructureMap) 主要项目(引用StructureMap项目-使用 类构造函数中的接口) StructureMap项目(IoC - For().Use();)

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