web-dev-qa-db-ja.com

C#は、パラメーターなしのコンストラクターなしでクラスをシリアル化します

3つの異なる暗号化クラスのファクトリパターンを実装しています。ファクトリは、どちらを作成するかを決定し、データベースから正しいクラスのシリアル化されたインスタンスを取得して、それをリクエスターに返します。現在、クラスをシリアル化してデータベースに保存する作業を行っています。 BouncyCastleというPGP暗号化クラス用に作成しています。ファイルからクラスとキーを作成できますが、シリアル化しようとすると、クラスPgpPublicKeyPgpPrivateKeyのオブジェクトである2つのメンバー変数は、シリアル化できないと表示されます。パラメータのないコンストラクタはありません。

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();
}

クラスには、問題となる2つのメンバー変数があります。

public class BouncyCastle : ICryptographyProvider
{

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

これは公開鍵クラスです。パラメータのないコンストラクタはありません。

public class PgpPublicKey
{
    public PgpPublicKey(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time);
    // cut other methods
}
13
Roger Bacon

シリアライザークラスは、逆シリアル化中に空の新しいインスタンスを作成するときに、シリアル化されたデータから取得したすべてのパブリックプロパティをコピーするため、パラメーターなしのコンストラクターが必要です。

パラメーターなしでコンストラクターを作成することを避けたい場合は、コンストラクターを簡単にプライベートにすることができます。

例:

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

    private PgpPublicKey();
    // cut other methods
}
30
Jamby

はい、XmlSerializerは、シリアル化が機能するために、パラメーターのないコンストラクターが存在する必要があります

次の答えから: XML-Serializableクラスにパラメーターのないコンストラクターが必要な理由

オブジェクトの逆シリアル化中に、オブジェクトの逆シリアル化を担当するクラスは、シリアル化されたクラスのインスタンスを作成し、入力するインスタンスを取得した後でのみ、シリアル化されたフィールドとプロパティの入力に進みます。

パラメータがない限り、必要に応じてコンストラクタをプライベートまたは内部にすることができます。

5
Magnum

DataContractSerializerは、パラメーターなしのコンストラクターを必要としません。代わりに必要なのは、クラスの特別な属性です。

2
alexkovelsky

PgpPublicKeyクラスとPgpPrivateKeyクラスはあなたが定義していますか?パラメータのないコンストラクタをそれらに追加するだけです。

外部からアクセスできるようにしたくない場合は、プライベートにすることができます。デシリアライザーは引き続きそれらにアクセスできます。

0
Peter Ivan

数年後もまだ探している人にとって、答えはFormatterServices.GetUninitializedObjectになりました。これはすべてnullと0に設定されたメモリの一部であり、オブジェクトのデフォルト値のフィールドがゼロ以外の場合は、間違って設定される可能性があるため、注意してください。「オブジェクトの新しいインスタンスが初期化されるためゼロに設定され、コンストラクターが実行されない場合、オブジェクトは、そのオブジェクトによって有効と見なされる状態を表していない可能性があります。」

0
Basalat Raja