代码合同和自动生成的文件
当我在 WPF 控制项目上启用代码协定时,我遇到了编译时创建的自动生成文件 (XamlNamespace.GenerateInternalTypeHelper) 的问题。请注意,生成的文件名为“GenerateInternalTypeHelper.g.cs”,与几篇过时博客文章中提到的“GenerateInternalTypeHelper.gics”不同。
我不太确定其目的是什么,但我假设某些内部反射对于解析 XAML 很重要。问题是它没有代码合约,代码合约系统也不够智能,无法将其识别为自动生成的文件。这会导致静态检查器出现一堆错误。
我尝试寻找此问题的解决方案,但似乎没有人开发 WPF 控件并使用代码契约。我确实遇到了一个有趣的属性,ContractVerificationAttribute,它采用一个布尔值来设置是否要验证程序集或类。这允许您将类装饰为未验证。遗憾的是,GenerateInternalTypeHelper 会在每次编译时重新生成,因此不可能仅排除这一类。不过,相反的情况也是可能的,将程序集装饰为未经验证,然后选择加入每个类。
为了减轻明显的黑客攻击,我想创建一个测试,至少可以通过如下测试来验证公开的类是否具有代码契约验证,以确保自己的类至少得到验证:
[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)。
(我还需要排除资源和设置,但我希望您明白)。
我不喜欢这个解决方案,因为有很多方法可以避免合同验证,但目前这是我能想到的最好的解决方案。如果有人有更好的解决方案,请告诉我。
When I enabled code contracts on my WPF control project I ran into a problem with an auto generated file which was created at compile time (XamlNamespace.GeneratedInternalTypeHelper). Note, the generated file is called GeneratedInternalTypeHelper.g.cs and is not the same as the GeneratedInternalTypeHelper.g.i.cs which there are several obsolete blog posts about.
I'm not exactly sure what its purpose is, but I am assuming it is important for some internal reflection to resolve XAML. The problem is that it does not have code contracts, nor is the code contract system smart enough to recognize it as an auto generated file. This leads to a bunch of errors from the static checker.
I tried searching for a solution to this problem, but it seems like nobody is developing WPF controls and using code contracts. I did come across an interesting attribute, ContractVerificationAttribute, which takes a boolean value to set whether the assembly or class is to be verified. This allows you to decorate a class as not verified. Sadly the GeneratedInternalTypeHelper is regenerated with every compile, so it is not possible to exclude just this one class. The inverse scenario is possible though, decorate the assembly as not verified and then opt in for every class.
To mitigate the obvious hack I wanted to create a test that would at least verify that the exposed classes have code contract verification with a test like the following to ensure that own classes were at least being verified:
[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);
}
As you can see it takes all classes in the controls assembly and finds the one from the company namespace which are not also auto generated anonymous types (<>WeirdClassName).
(I also need to exclude Resources and settings, but I hope you get the idea).
I'm not loving the solution since there are ways of avoiding contract verification, but currently it's the best I can come up with. If anyone has a better solution, please let me know.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因此,您可以像对待任何其他“第 3 方”类或库一样对待此类。我确信某些假设适用于与此生成的类的交互,因此在交互点,用
Contract.Assume(result != null)
或类似的代码装饰您自己的代码。其作用是转换为在运行时检查的断言,但它允许静态分析器推理您控制的其余代码。
So you can treat this class exactly like you would treat any other "3rd party" class or library. I'm sure certain assumptions would hold with the interaction with this generated class so at the interaction points, decorate your own code with
Contract.Assume(result != null)
or similar.What this does is translate into an assertion that is checked at run time, but it allows the static analyzer to reason about the rest of the code that you do control.