Expand|Select|Wrap|Line Numbers
- public abstract class XmlSerializableItem<T>
- {
- public string ToXml()
- {
- XmlSerializer xs = new XmlSerializer( this.GetType() );
- TextWriter xw
- = new StringWriter( CultureInfo.InvariantCulture );
- xs.Serialize( xw, this );
- return Convert.ToString( xw, CultureInfo.InvariantCulture );
- }
- [SuppressMessage("Microsoft.Design",
- "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
- public static T FromXml( string xml )
- {
- XmlSerializer xs = new XmlSerializer( typeof( T ) );
- TextReader tr = new StringReader( xml );
- return (T) xs.Deserialize( tr );
- }
- }
Expand|Select|Wrap|Line Numbers
- public class MyDerived : XmlSerializableItem<MyDerived>
- {
- /* add some properties etc */
- }
Expand|Select|Wrap|Line Numbers
- MyDerived d1 = new MyDerived(); // assume a suitable constructor has been implemented
- string xml = d1.ToXml();
- MyDerived d2 = MyDerived.FromXml( xml );
The reason the base type needs to be generic is so that I can use the type parameter T as the return type of the FromXml method.
The problem is that the FromXml method throws a FxCop warning CA1000:DoNotDeclareStaticMembersOnGenericTypes. Microsoft seem to be quite emphatic that warning CA1000 should not be suppressed although I'm not sure I agree in this case. Their reason is
// Static method in a generic type.Except in this case the type parameter is supplied in the derived type's class declaration and does not need to be provided when the derived type is used - the XmlSerializableItem class is effectively hidden from consumers of the derived type.
GenericType<int>.StaticMethod();
// Generic instance method that does not support inference.
someObject.GenericMethod<int>();
Generally, both of the prior declarations should be avoided so that the type argument does not have to be specified when the member is called. This results in a syntax for calling members in generics that is no different from the syntax for non-generics.
If I follow Microsoft's suggestion and change FromXml from a static method to an instance method then the derived type becomes, if anything, more difficult to use:
Expand|Select|Wrap|Line Numbers
- MyDerived d1 = new MyDerived(); // assume a suitable constructor has been implemented
- string xml = MyDerived.ToXml();
- MyDerived d2 = new MyDerived();
- MyDerived d2 = d2.FromXml( xml );
Maybe I'm missing something, and there's another way of providing this deserialization functionality in a base type without violating any FxCop rules. Or maybe Microsoft have got it wrong and this rule shouldn't apply to static members on abstract base types. Any thoughts on this subject much appreciated...
Thanks
Simon.