为遗留库创建代码合同

时间:2010-10-22 16:07:31

标签: c# code-contracts

最终目标是为一个我无法控制的外部程序集中的类指定合同(即我不能直接向该类添加合同)。

到目前为止我尝试过:

  1. ContractClassFor属性。
    不起作用,因为目标类必须指向合同类。

  2. 通过对自动生成的方法进行逆向工程,手动构建合同引用程序集(即MyAsm.Contracts.dll)。
    不起作用,因为在我编译之后,重写器开始并且方便地剥离ContractDeclarativeAssembly属性,这使得组件无法被工具识别为“合同参考组件”。我无法找到一种方法来关闭重写器。

  3. 创建一个具有相同名称,版本,强名称(如果有)和其他属性作为目标程序集的“伪”程序集,并在其中放置具有相同名称方法的同名类。然后在打开“构建合同引用”选项的情况下编译该程序集,然后获取生成的合同引用程序集并使用它 由于某些原因,这也没有用,虽然我不知道究竟是什么原因。静态检查器只是忽略了我的smartypants生成的引用程序集,就好像它不存在一样。

  4. 还有一件事,以防万一重要:目标程序集是为.NET 2.0编译的,我无法为4.0重新编译它。

    更新

    用定义的合同编写“包装”库是不可能的。

    首先,它需要编写很多额外的代码。但即使你把它放在一边,也可能是一个显着的性能损失:我必须(可能)为每个“遗留”类型创建包装类,从我的“遗留”方法用作返回类型。但即使这不是故事的结尾。想象一下,某些方法可能会返回对基接口的引用,然后调用代码可能会将它们转换为派生接口,以查看该对象是否支持更多功能。我如何包装那些?我可能必须在我的包装类上提供自定义Cast<T>()方法,如果成功,它将尝试转换底层类/接口并返回结果包装器。最后,我的整个代码库将变得如此复杂,无论如何它可能都不值得。

    另一方面,CC团队本身已经成功地解决了这个问题:他们确实为mscorlib,System.Core和其他一些系统组件提供了合适的合同参考组件,不是吗?他们是如何建立起来的?如果他们能够做到这一点,那么我认为没有任何理由说明我不应该做出同样的伎俩。

    哦,实际上,我确实看到了一个原因:我不知道该怎么做。 :-) - Fyodor Soikin 18秒前编辑

2 个答案:

答案 0 :(得分:4)

你可能差不多有(2)。请务必关闭您手动构建的C#程序集的合同重写。关闭所有运行时检查和静态分析,重写器不应该启动。将它放在所有其他CodeContracts程序集的任何地方,例如对于/bin/X.dll,将程序集转到/bin/CodeContracts/X.Contracts.dll。

http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/5fe7ad4e-d4f1-4bb5-806e-a1e31f550181。你是对的 - 只需通过查看Reflector创建所有正确的位,然后就可以了。我想这样做是为了将合同添加到我的F#程序集中,直到F#可以处理合同。

答案 1 :(得分:1)

解决方法可能是在代码和外部程序集之间创建一个“Facade”图层。该层可以保存您在外部代码上应用的所有合同。

如果您不想更改现有代码中的任何内容,我担心您无法做更多事情。