FxCop规则以特定方式访问属性

时间:2014-01-03 10:29:42

标签: c# fxcop

我有一个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),而是如何从代码中的其他地方调用它们。

2 个答案:

答案 0 :(得分:1)

由于您正在查看代码中其他位置的属性,因此您需要使用BaseIntrospectionRule的访问者模式支持来查找对有问题的属性的引用。

只有已分析程序集的内容才会传递给Check,因此如果仅引用包含ItemFieldsCollection的程序集而不是分析,则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