代码合同和自动生成的文件

时间:2010-08-05 14:16:56

标签: wpf-controls code-contracts

当我在WPF控件项目上启用代码契约时,遇到了在编译时创建的自动生成文件的问题(XamlNamespace.GeneratedInternalTypeHelper)。请注意,生成的文件名为GeneratedInternalTypeHelper.g.cs,与GeneratedInternalTypeHelper.g.i.cs不同,后者有几篇过时的博客文章。

我不确定它的用途是什么,但我认为解决XAML对于某些内部反射非常重要。问题是它没有代码契约,代码契约系统也不够智能,无法将其识别为自动生成的文件。这会导致静态检查器出现一堆错误。

我试图寻找这个问题的解决方案,但似乎没有人在开发WPF控件并使用代码契约。我确实遇到了一个有趣的属性,ContractVerificationAttribute,它接受一个布尔值来设置是否要验证程序集或类。这允许您装饰未经验证的类。遗憾的是GeneratedInternalTypeHelper会在每次编译时重新生成,因此不可能只排除这一个类。反过来的情况是可能的,将程序集装饰为未经验证,然后选择加入每个类。

为了缓解明显的黑客攻击,我想创建一个测试,至少可以验证公开的类是否通过以下测试进行代码合同验证,以确保自己的类至少得到验证:

[Fact]
public void AllAssemblyTypesAreDecoratedWithContractVerificationTrue()
{
    var assembly = typeof(someType).Assembly;
    var exposedTypes = assembly.GetTypes().Where(t=>!string.IsNullOrWhiteSpace(t.Namespace) && t.Namespace.StartsWith("MyNamespace") && !t.Name.StartsWith("<>"));

    var areAnyNotContractVerified = exposedTypes.Any(t =>
    {
        var verificationAttribute = t.GetCustomAttributes(typeof(ContractVerificationAttribute), true).OfType<ContractVerificationAttribute>();
        return verificationAttribute.Any() && verificationAttribute.First().Value;
    });

    Assert.False(areAnyNotContractVerified);
}

正如您所看到的,它需要控件程序集中的所有类,并从公司名称空间中找到一个也不是自动生成的匿名类型(&lt;&gt; WeirdClassName)。

(我还需要排除资源和设置,但我希望你明白这一点。)

我不喜欢这个解决方案,因为有办法避免合同验证,但目前这是我能想到的最好的方法。如果有人有更好的解决方案,请告诉我。

1 个答案:

答案 0 :(得分:0)

因此,您可以像处理任何其他“第三方”类或库一样对待此类。我确信某些假设与这个生成的类的交互有关,所以在交互点,用Contract.Assume(result != null)或类似的东西装饰你自己的代码。

var result = new GennedClass().GetSomeValue();
Contract.Assume(result != null);

这样做会转化为在运行时检查的断言,但它允许静态分析器推断您控制的其余代码。