I've got an Item class (to which I have no access), which has two different ways to access Fields of the Item. I'd like to have a custom FxCop rule that prefers one over the other.
I can get the value from a specific field by having an item and directly accessing item["fieldname"]
, which will return a string.
The code for this:
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;
}
}
Alternatively, I can access the Field property like so: item.Fields["Fieldname"].Value
.
The code for the alternative:
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;
}
}
This approach can throw a NullReferenceException
, for instance if the fieldname is misspelled. The Field
object will then be null
, so the Value can't be retrieved.
Now, as the first way is safer, I'd like to give a warning when the second method is used. I've found that I'll need to use the
public override ProblemCollection Check(Member member)
{
}
method, and then cast the member to a Microsoft.FxCop.Sdk.PropertyNode
. From there however, I don't know how to go about it, especially because they use the same code at the end (the first option calls the second option, but if the fieldname is misspelled and the field is null, the first option will just return an empty string).
Alternatively, if that's not possible, I'd like to give an FxCop error if the second option is used without checking for the null value of the Field.
Some administrative details: I'm using Visual Studio 2012 with FxCop 10.
Edit
Just to clarify further, this rule shouldn't check the properties themselves(i.e. something like the Naming.IdentifiersShouldBeCasedCorrectly
), but how they are called from elsewhere in the code.