代码合同重写失败,"无法解析成员引用"

Wal*_*rey 7 .net c# code-contracts

请注意,这可能此问题重复,我不完全确定.

我的问题是我有一个类库项目,它引用了第三方类型库(COM).我想将契约放入类库中的方法,如下所示:

public class foo
{
    public static int divide(TypeFromTypeLib tftl, int a, int b)
    {
        Contract.Requires<ArgumentException>(b != 0);
        return a / b;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后让客户项目使用这种方法,例如

var n = foo.divide(null, 4, 2);
Run Code Online (Sandbox Code Playgroud)

但我也希望客户端项目在其某些方法中也使用契约.因此,我将两个项目的Code Contracts属性设置为'执行运行时合同检查'(没有它,您将获得运行时断言,告诉您它需要此设置).

现在,当我尝试编译客户端时,我收到以下错误:

无法解析成员引用:my_class_lib.foo::divide.

ccrewrite:error:由于元数据错误而重写中止.

这似乎是不可避免的 - 任何时候调用一个类型来自第三方类型库的方法.从方法的签名中删除类型,没关系.

谁能解释为什么会这样?这是一个线索,我的代码结构从根本上是有缺陷的(如果是,为什么?),或者它是代码合同的怪癖?是否有针对此问题的建议修复程序?

Mic*_*ski 3

老实说,我不知道为什么ccrewrite在互操作类型上有问题,但我可以给你 3 个解决方法:

解决方案1

这是最简单的:

  • 转到项目的参考列表。
  • 查找第三方类型库。
  • 右键点击。
  • 从上下文菜单中选择属性
  • 将嵌入互操作类型从 True更改为 False。

您必须为这两个项目执行此操作。此解决方案的缺点是,构建后,您将在 bin 文件夹中获得额外的互操作程序集。

解决方案2

另一个解决方案可能是从公共接口中删除第三方类型库中的类型,即:

public class foo
{
    public static int divide(int a, int b)
    {
        return divide(null, a, b);
    }

    private static int divide(TypeFromTypeLib tftl, int a, int b)
    {
        Contract.Requires<ArgumentException>(b != 0);
        return a / b;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,只有当您不需要TypeFromTypeLib在客户端中使用时才可以这样做。

解决方案3

如果您需要TypeFromTypeLib在客户端中使用,您可以为此类编写一个包装器,即:

public class MyTypeFromTypeLib
{
   //...
}

public class foo
{
    public static int divide(MyTypeFromTypeLib mytftl, int a, int b)
    {
        var tftl = new TypeFromTypeLib();
        //Map MyTypeFromTypeLib  to TypeFromTypeLib 
        //...
        return divide(tftl , a, b);
    }

    private static int divide(TypeFromTypeLib tftl, int a, int b)
    {
        Contract.Requires<ArgumentException>(b != 0);
        return a / b;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这个解决方案很麻烦,因为需要额外的类。