I have some Field objects that need to be serialized. Their primary string identifier is called a Tag and starts with a number, so it's not suitable for use as a class name. Thus, for a field bearing tag 32A
, I am using the name Field32A
. However, during serialization, I need access to the literal string value "32A"
.
I don't think it's a good idea to convert the name of the class to a string and substring the 32A
off the end (though I'm open to hearing argument). And, instead of hard-coding this string in the serialization logic somewhere deep in the class, I thought of putting the string in an attribute that can decorate the class itself, in close proximity to the class name in the source code, so future developers who (say) copy this class to a new one won't miss the need to change the class name and the string representing the tag value.
Note: the FieldTag attribute on the FieldBase class is just there to prove that we’re getting the right fieldtag (and in some cases I did incorrectly get the base class field tag, such as when it was omitted on the derived class, until I put the inherit: false
in there).
The magic here is occurring inside the Field32A.ToString method where it refers to FieldTag
, which goes to the property on the base class and gets the value from the attribute. Do you think this is a good idea?
Run the following code live in a DotNetFiddle
[FieldTag("Base")]
public abstract class FieldBase {
public string FieldTag {
get {
FieldTagAttribute fieldTagAttribute = (FieldTagAttribute) (
GetType().GetCustomAttribute(typeof(FieldTagAttribute), inherit: false)
);
if (fieldTagAttribute == null) {
throw new InvalidOperationException(String.Format(
"Class {0} has no attribute [FieldTag]. "
+ "Please add the attribute to this class.", GetType()));
}
return fieldTagAttribute.FieldTag;
}
}
}
public class FieldTagAttribute : Attribute {
public FieldTagAttribute(string fieldTag) {
FieldTag = fieldTag;
}
public string FieldTag { get; set; }
}
[FieldTag("32A")]
public class Field32A : FieldBase {
public string Value{ get; set; }
public override string ToString() {
return ":" + FieldTag + ":" + Value;
}
}
void Main() {
Field32A field32A = new Field32A { Value = "12345" };
field32A.ToString().Dump(); // :32A:12345
}
FieldBase
class. At that point, you can cache the retrieved value in a class member and not have to do any reflection in the property getter at all. \$\endgroup\$