2

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

我不完全确定它的目的是什么,但我假设某些内部反射对解决 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);
}

正如您所看到的,它获取控件程序集中的所有类,并从公司命名空间中找到不是自动生成的匿名类型(<>WeirdClassName)的类。

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

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

4

1 回答 1

0

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

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

它的作用是转换为在运行时检查的断言,但它允许静态分析器推断您控制的其余代码。

于 2011-11-16T07:00:12.030 回答