Search code examples
c#poco

Can a POCO contain a constructor?


Can a POCO contain a constructor? Could you tell me if this class is correct? I also read that a POCO must have a parameterless constructor. Is that correct and why? If I accept this parameterless constructor, I'll have a problem with my read only Id property. For me, it seems logical that if this property must be read-only, then the only way to initialize it is in the constructor.

[DataContract]
public class MembershipUser
{
    public MembershipUser(Guid idValue)
    {
        this.Id = idValue;
    }

    [DataMember]
    public virtual readonly Guid Id { get; set; }

    [DataMember]
    public virtual string UserName { get; set; }

    [DataMember]
    public virtual string Email { get; set; }
}

Solution

  • A POCO object can contain other constructors but a default constructor is needed for deserialization as that process tries to create a default instance of the object and then sets the properties.

    After some research it seems that the datacontract serializer does not use or even call the default constructor. Using this you could exclude a default ctor and still serialize your POCO. Whether or not you should is an implementation detail that you and your team would have to decide.

    DataContractSerializer Tests:

    [Test]
    public void SerializerTest()
    {
        var s = new SerializeMe(2);
        s.Name = "Test";
        DataContractSerializer dcs = new DataContractSerializer(typeof(SerializeMe));
        Stream ms = new MemoryStream();
        var writer = XmlWriter.Create(ms);
        Assert.DoesNotThrow(() => dcs.WriteObject(writer, s));
        writer.Close();
    
        ms.Position = 0;
        var reader = new StreamReader(ms);
        var xml = reader.ReadToEnd();
        Console.WriteLine(xml);
    }
    
    [Test]
    public void DeserializeTest()
    {
        var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><SerializeMe xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/Test\"><Id>2</Id><Name>Test</Name></SerializeMe>";
        DataContractSerializer dcs = new DataContractSerializer(typeof(SerializeMe));            
        XmlReader reader = XmlReader.Create(new StringReader(xml));
        var obj = dcs.ReadObject(reader) as SerializeMe;
        Assert.AreEqual(obj.Name, "Test");
    }
    
    [DataContract]
    public class SerializeMe
    {
        public SerializeMe(int id)
        {
            this.Id = id;
        }
        [DataMember]
        public int Id { get; private set; }
        [DataMember]
        public string Name { get; set; }
    }