views:

53

answers:

3

I have a class which communicates with an API and needs to do some transformations to any data it touches. This class is the equivalent too:

public class SerializeMe
{
    public SerializeMe(string someString)
    {
        _someString = someString;
    }

    private string _someString;
    public string TransformedValue
    {
        get { _someString = TransformToSomething();
              return _someString; }
        set { _someString = value; }
    }
}

For my API callers I log every request and response by serializing these classes. They act as xml schemas almost.

Now everything works perfectly my only issue is that somebody could theoretically try and set and end up not getting their expected results back. Its mainly a design issue just trying to make my code responsible. I'd love to be able to use a private set on this but the XmlSerializer complains about it.

Is there a attribute or another technique to be able to make Transformed value as unsettable except by the serializer?

Also If there isn't an option, making the property as Obsolete is an option. Is there any other more appropriate attribute to use?

A: 

Unfortunately the XmlSerializer can only serialize properties with public getters/setters (unless, of course, you specify your own serialization via IXmlSerializable).

The only workaround that I have used from time to time (and it's a hack and doesn't conform to .NET design guidelines so I don't like to do it at all) is have a public property with an empty setter and then use another method to set the private backing variable:

public class SerializeMe
{
    private string _someString;
    public string SomeString
    {
        get
        {
            _someString = TransformToSomething();
            return _someString;
        }
        set { }
    }

    public void SetString(string val) { _someString = val; }
}

Obviously IXmlSerializable is more work, but it is definitely a better decision in the long run (not to mention the fact that it's not a hack).

Justin Niessner
+2  A: 

The XmlSerializer does a lot out of the box but to get the flexablity you are after you should look at using the IXmlSerializable interface. The XmlSerializer will look at the object and if it implements IXmlSerializable it will call the methods on the object exposed by the interface. Yes it is more work but you have a more fine grained approach as to how your object is de/serialized.

Bronumski
+2  A: 

That is a pain with XmlSerializer, bur fine with DataContractSerialzer (which can also work without the parameterless ctor that XmlSerializer needs). Just mark the type as [DataContract], and the field (not property) as [DataMember].

[DataContract]
public class SerializeMe
{
    public SerializeMe(string someString)
    {
        _someString = someString;
    }
    [DataMember]
    private string _someString;
    public string TransformedValue
    {
        get { _someString = TransformToSomething();
              return _someString; }
        private set { _someString = value; }
    }
}
Marc Gravell
Also the DataContractSerializer is more performant than the XmlSerializer and can handle fields as well as properties. One downside is that you cannot control the structure of the Xml so if you need it to be in a particular format you won't be able to use it.
Bronumski
@bronumski if performance was the key aim, I'd be using protobuf-net instead :)
Marc Gravell