当我在我的 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)的类。
(我还需要排除资源和设置,但我希望你明白)。
我不喜欢这个解决方案,因为有一些方法可以避免合同验证,但目前这是我能想到的最好的方法。如果有人有更好的解决方案,请告诉我。