我有一个Item类(我没有访问权限),它有两种不同的方式来访问Item的Fields。我希望有一个自定义的FxCop规则,优先选择其中一个。
我可以通过拥有一个项目并直接访问item["fieldname"]
来获取特定字段的值,这将返回一个字符串。
代码:
public string this[string fieldName]
{
get
{
Assert.ArgumentNotNullOrEmpty(fieldName, "fieldName");
ID result;
if (ID.TryParse(fieldName, out result))
return this[result];
if ((int) fieldName[0] == 64)
return this.Fields.GetSpecialField(fieldName);
Field field = this.Fields[fieldName];
if (field == null)
return "";
else
return field.Value;
}
set
{
Assert.ArgumentNotNullOrEmpty(fieldName, "fieldName");
ID result;
if (ID.TryParse(fieldName, out result))
{
this[result] = value;
}
else
{
Field field = this.Fields[fieldName];
if (field == null)
return;
field.Value = value;
}
}
}
public string this[int index]
{
get
{
Field field = this.Fields[index];
if (field == null)
return "";
else
return field.Value;
}
set
{
Field field = this.Fields[index];
if (field == null)
return;
field.Value = value;
}
}
public string this[ID fieldID]
{
get
{
Assert.ArgumentNotNull((object) fieldID, "fieldID");
return this.Fields[fieldID].Value;
}
set
{
Assert.ArgumentNotNull((object) fieldID, "fieldID");
this.Fields[fieldID].Value = value;
}
}
或者,我可以像这样访问Field属性:item.Fields["Fieldname"].Value
。
备选代码:
public Field this[ID fieldID]
{
get
{
return new Field(fieldID, this._ownerItem);
}
}
public Field this[string fieldName]
{
get
{
ID fieldId = TemplateManager.GetFieldId(fieldName, this.TemplateId, this.Database);
if (fieldId == null)
return (Field) null;
else
return this[fieldId];
}
}
public Field this[int index]
{
get
{
Field[] fields = this.GetFields();
if (index < fields.Length && index >= 0)
return fields[index];
else
return (Field) null;
}
}
这种方法可以抛出NullReferenceException
,例如,如果字段名拼写错误。 Field
对象将为null
,因此无法检索值。
现在,由于第一种方式更安全,我想在使用第二种方法时发出警告。我发现我需要使用
public override ProblemCollection Check(Member member)
{
}
方法,然后将成员强制转换为Microsoft.FxCop.Sdk.PropertyNode
。然而,从那里,我不知道如何去做,特别是因为他们在最后使用相同的代码(第一个选项调用第二个选项,但如果字段名拼写错误且字段为空,则第一个选项将只返回一个空字符串)。
或者,如果那是不可能的,如果使用第二个选项而不检查Field的空值,我想给出一个FxCop错误。
一些管理细节:我正在使用带有FxCop 10的Visual Studio 2012。
修改
只是为了进一步澄清,这条规则不应该检查属性本身(即类似Naming.IdentifiersShouldBeCasedCorrectly
),而是如何从代码中的其他地方调用它们。
答案 0 :(得分:1)
由于您正在查看代码中其他位置的属性,因此您需要使用BaseIntrospectionRule
的访问者模式支持来查找对有问题的属性的引用。
只有已分析程序集的内容才会传递给Check
,因此如果仅引用包含Item
和FieldsCollection
的程序集而不是分析,则Item
索引器不应该不会引起问题。
如果不深入研究数据流分析(这大大超出了Introspector的范围),您可以通过在所有已分析的方法体中运行访问者并标记Field.Value
getter的调用来进行非常粗略的近似:
public override ProblemCollection Check(Member member)
{
var method = member as Method;
if (method != null)
{
VisitStatements(method.Body.Statements);
}
return Problems;
}
public override void VisitMethodCall(MethodCall methodCall)
{
var memberBinding = methodCall.Callee as MemberBinding;
if (memberBinding != null)
{
var methodCalled = memberBinding.BoundMember as Method;
if (methodCalled != null)
{
if (methodCalled.FullName == "Some.Namespace.Field.get_Value")
Problems.Add(new Problem(GetResolution(), methodCall));
}
}
base.VisitMethodCall(methodCall);
}
更好的近似值也会遍历Operand
的第0 MethodCall
条,只会在Operand
调用FieldsCollection
索引器时引发问题。
答案 1 :(得分:0)
为什么不使用de ObsoleteAttribute?