C# serialize a class without a parameterless constructor
Asked Answered
C

5

19

I'm implementing a factory pattern for 3 different cryptography classes. The factory will determine which one to create and then get a serialized instance of the correct class from a database and return it to the requester. Right now I'm working on serializing the classes to store them in the database. I'm writing one for a PGP cryptography class called BouncyCastle. I can create the class and the keys from files but when I try to serialize it, it says that the two member variables, which are objects of class PgpPublicKey, and PgpPrivateKey, cannot be serialized because they do not have parameterless constructors.

public void createdBouncyFromFiles()
{
    var bc = new BouncyCastle("C:\\TestFiles\\BouncyPublicKey.txt", "C:\\TestFiles\\BouncyPrivateKey.txt", "Password1");
    var xmlSerializer = new XmlSerializer(bc.GetType());
    var textWriter = new StringWriter();
    xmlSerializer.Serialize(textWriter, bc);
    var theSerializedClass = textWriter.ToString();
}

The class has two member variables that are the problem.

public class BouncyCastle : ICryptographyProvider
{

    public PgpPublicKey m_publicKey;
    public PgpPrivateKey m_privateKey;
    public string m_passPhrase;
    // cut out the irelevant parts

This is the public key class. No parameterless constructor.

public class PgpPublicKey
{
    public PgpPublicKey(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time);
    // cut other methods
}
Churchman answered 4/3, 2013 at 22:5 Comment(2)
Make your own data class to serialize, copy values around as neededDispeople
Why you don't want to just add parameterless constructors?Clubby
C
36

Any Serializer Class need a parameterless constructor because, while deserializing it create an empty new instance, then it copies every public property taken from seialized data.

You can easily make the constructor private, if you want to avoid to create it without parameters.

EX:

public class PgpPublicKey
{
    public PgpPublicKey(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time);

    private PgpPublicKey();
    // cut other methods
}
Calcite answered 4/3, 2013 at 22:11 Comment(2)
i tried the private parameterless constructor and it doesn't work that way for me. i need to make it public for it to deserialize properlyAubergine
How does it work for you?Dropper
F
5

Yes, the XmlSerializer requires a parameterless constructor to exist in order for the serialization to work.

From the following answer: Why XML-Serializable class need a parameterless constructor

During an object's de-serialization, the class responsible for de-serializing an object creates an instance of the serialized class and then proceeds to populate the serialized fields and properties only after acquiring an instance to populate.

You can make your constructor private or internal if you want, just so long as its parameterless.

Foretooth answered 4/3, 2013 at 22:11 Comment(0)
P
2

DataContractSerializer does not require parameterless constructor. What it instead requires are special attributes of class.

Pup answered 23/2, 2015 at 8:39 Comment(0)
W
0

Are PgpPublicKey and PgpPrivateKey classes defined by you? Simply add parameterless constructors to them.

They can be private if you don't want to make them accessible from outside. The deserializer can still access them.

Winzler answered 4/3, 2013 at 22:28 Comment(0)
A
0

For anyone who is still looking a few years later, the answer is now FormatterServices.GetUninitializedObject. Be careful with it, as this is just a piece of memory set to all nulls and zeros and if a field in the object's default value is something other than zero, it might be set wrong: "Because the new instance of the object is initialized to zero and no constructors are run, the object might not represent a state that is regarded as valid by that object."

Archfiend answered 7/1, 2020 at 18:0 Comment(1)
I wasn't even aware of this feature, thanks for the tip! I'm sure it'll come handy some day. Here's the link to MSDN: learn.microsoft.com/en-us/dotnet/api/…Pskov

© 2022 - 2024 — McMap. All rights reserved.