自定义FxCop规则示例之一:AvoidICloneableImplementation
在2年前的Tech Ed China上就有过FxCop的介绍,当时译为“框架警察”。关于FxCop的介绍和若干规则示例,可以参考John Robbins所写的Bad Code? FxCop to the Rescue和Three Vital FXCop Rules文章。本系列将由浅入深的解释定制FxCop的常用方式和技巧。
在设计新类时要避免实现ICloneable的Blog中仅仅解释了其原因。对于Design Guideline的实施,可以经常得到FxCop的帮助。既然FxCop自带的规则还没有包括对这一设计指导的检查,让我们自己来写一个这样的规则。全部步骤如下。使用的是.NET框架1.1和VS2003和FxCop 1.312版本,注意FxCop规则编程现在并没有得到官方支持。如果以后版本API发生变化,我会对示例程序有选择的更新。
- 下载FxCop 1.312: http://www.gotdotnet.com/team/fxcop/ 选择FxCop for .NET 1.1.
- 安装FxCop 1.312, 其缺省安装在“%ProgramFiles%"Microsoft FxCop 1.312”文件夹下。注意其中包括的FxCopSdk.dll和Microsoft.Cci.DLL这2个程序集(assembly)。我们的规则项目需要引用它们。
- 启动FxCop, 留意到在Rules Tab下所有预先提供的Rules.
- 将设计新类时要避免实现ICloneable中提供的测试用例编译成为一个Class library起名为FxCopRuleTests。
- 通过菜单,工具栏或者Ctrl+Shift+A以增加Target,即这些Rule将检查的程序集。添加FxCopRuleTests。
- 通过菜单,工具栏或者F5开始分析。结果有7条violation messages,但是没有设计新类时要避免实现ICloneable相关的消息。我们现在就开始写这样的一个FxCop Rule.
- 使用VS2003创建新的Class Library项目起名CustomFxCopRules.
- 删除IDE创建的Class1.cs和AssemblyInfo.cs.
- 添加对FxCopSdk.dll和Microsoft.Cci.DLL的引用
- 增加一个类文件叫做AvoidICloneableImplementation.cs.
- 添加一个命名为RuleInfo.xml的XML文件,设置其Build Action为Embedded Resource.
- 使用如下的代码,实现这一简单的FxCop Rule,编译后通过菜单,工具栏或者Ctrl+R加入FxCop的Rule之中,再运行FxCop看到正确结果。(提示,可以uncheck所有FxCop自带规则以减少干扰。
这是RuleInfo.xml
<?xmlversion="1.0"encoding="utf-8"?>
<RulesFriendlyName="Custom FxCop Rules">
<RuleTypeName="AvoidICloneableImplementation"Category="ZhanboBlog.Demo"CheckId="ZB001">
<Name>Avoid ICloneable Implementation</Name>
<Description>ICloneable could be used to return either deep copy or shallow copy, and is therefore not useful.</Description>
<Url>http://blog.joycode.com/zhanbos/archive/2005/03/13/45707.aspx</Url>
<Resolution>Type '{0}' Implements ICloneable, which should be avoided.</Resolution>
<Email/>
<MessageLevelCertainty="99">Error</MessageLevel>
<FixCategories>Breaking</FixCategories>
<Owner/>
</Rule>
</Rules>
这是AvoidICloneableImplementation.cs
using System;
using Microsoft.Cci;
using Microsoft.Tools.FxCop.Sdk;
using Microsoft.Tools.FxCop.Sdk.Introspection;
namespace ZhanboBlog.Demo.CustomRules
{
///<summary>
/// Do not implement ICloneable interface
///</summary>
public class AvoidICloneableImplementation : BaseIntrospectionRule
{
public AvoidICloneableImplementation() :
base("AvoidICloneableImplementation", "ZhanboBlog.Demo.CustomRules.RuleInfo", typeof(AvoidICloneableImplementation).Assembly)
{
}
public override ProblemCollection Check(TypeNode type)
{
if (DoesImplementICloneable(type.Interfaces))
{
Resolution resolution = GetResolution(RuleUtilities.Format(type));
Problem newProblem = new Problem(resolution, type);
Problems.Add(newProblem);
return Problems;
}
return null;
}
private bool DoesImplementICloneable(InterfaceList interfaceList)
{
for(int i = 0; i < interfaceList.Length; i++)
{
if (interfaceList[i] == SystemTypes.ICloneable)
{
return true;
}
}
return false;
}
}
}
如果您对某些代码有疑惑,可以留下评论我会在下一次Blog中提供必须的解释。通过实践会加深认识。您有什么希望增加FxCop规则检查的情形也欢迎提出,作为以后FxCop示例的参考。