2

私のクラスには、デフォルトのシリアライザーで生成されるものとは異なる XML 構造を使用してシリアライズ/デシリアライズするためのメソッドがあります。メソッドは私の型の XmlSerializer を作成しますが、オーバーライドがたくさんあります。これらのメソッドが呼び出されると、内部的に .NET がまだシリアル化アセンブリを生成していると思いますが、コンパイル後にこのアセンブリを生成したいので、実行時に生成されません。このカスタム シリアル化のシリアル化アセンブリを生成するにはどうすればよいですか? そのタイプに sgen.exe を使用すると、デフォルトのシリアライザーのみが生成されるように見えます。

特に、シリアライゼーション アセンブリを生成する必要があるのは、コードが保護モードで実行される Internet Explorer プロセス内から呼び出されるためです。.net ランタイムがシリアル化アセンブリを生成しようとすると、csc.exe が呼び出され、このプロセスの実行を許可するかどうかを確認するメッセージがユーザーに表示されます。ユーザーにプロンプ​​トを表示させたくない! そのため、すべてのシリアライゼーション/デシリアライゼーションを csc.exe なしで行う必要があります。

考えられる 1 つのオプションは、実行時に生成された .cs をキャプチャし、それを別のアセンブリに配置してから、それを製品に含めることです。少し厄介なことは別として、ビルドプロセスの一部としてその.csを自動生成する方法の問題が発生します...

おそらく言及する価値があります。私のカスタム xml シリアライゼーションは、ネストされたクラスもシリアライズするため、自動生成されたシリアライザーも存在する可能性があります。私のカスタム シリアル化は、主に以下の行に沿って実行されます。一部のプロパティに XmlIgnore を追加し、他のプロパティから XmlIgnore を削除します。これらのプロパティの多くは、シリアル化が必要なオブジェクトを返します。一部は IXmlSerializable を実装し、一部は既定のシリアル化を使用します。

    public void SerializeToCustomXml1(XmlWriter writer)
    {
        try
        {
            CustomXmlSerializer1.Serialize(writer, this);
        }
        catch (Exception)
        {
        }
    }

    /// <summary>
    /// Static serializer so it's created just once. There's another one like this CustomXmlSerializer2 with a slightly different format again.
    /// </summary>
    private static XmlSerializer CustomXmlSerializer1
    {
        get
        {
            if (_customXmlSerializer == null)
            {
                XmlAttributes dontIgnore = new XmlAttributes();
                dontIgnore.XmlIgnore = false;

                XmlAttributes attributes;
                XmlAttributeOverrides overrides = new XmlAttributeOverrides();

                // Include some fields in the XML that wouldn't be there otherwise.
                overrides.Add(typeof (WebResource), "ID", dontIgnore);
                overrides.Add(typeof (WebResource), "HasDestinationURLs", dontIgnore);
                overrides.Add(typeof (Resource), "AccessDefindBy", dontIgnore);

                attributes = new XmlAttributes();
                attributes.XmlIgnore = false;
                attributes.XmlElements.Add(new XmlElementAttribute("ActionID"));
                overrides.Add(typeof(Action), "ID", attributes);

                // Instead of serializing the Actions field we serialize CustomActionsXmlSerializer,
                // which outputs different content in the XML
                overrides.Add(typeof (WebResource), "Actions", ignore);
                attributes = new XmlAttributes();
                attributes.XmlIgnore = false;
                attributes.XmlElements.Add(new XmlElementAttribute("Actions"));
                overrides.Add(typeof (WebResource), "CustomActionsXmlSerializer", attributes);                  

                // ... more of these overrides here ... 
                _customXmlSerializer1 = new XmlSerializer(typeof(WebResource), overrides);
            }
            return _customXmlSerializer1;
        }

ここここに相互投稿。

更新: ああ、この回答は、XmlOverrides を使用している場合、XmlSerializer がプリコンパイル済みアセンブリを検索することさえできないため、不可能であることを示唆しています。ダーン。次に、シリアル化コードを生成してプロジェクトに含め、XmlSerializer を呼び出す代わりにそれを直接呼び出すのが最善の方法だと思います。これをきちんと行う方法について何か考えはありますか?

4

2 に答える 2

2

「カスタム XmlSerializer」とはSystem.Xml.XmlSerializer、カスタム シリアル化コードを使用することを意味する場合 (IXmlSerializableまたは[XmlElement]属性とフレンドを介して)、シリアル化時に呼び出されるアセンブリを探す必要がありますMyAssembly.XmlSerializers.dll

アセンブリの名前付けは重要です。アセンブリが検索されているかどうか、および検索されている正確なアセンブリ名がわからない場合は、AppDomain.CurrentDomain.FirstChanceExceptionアセンブリを含むアプリ ドメイン内のすべての例外に対して発生するイベント ハンドラーをアタッチするだけです。ロード例外。また、アセンブリが最初にアプリ ドメインに読み込まれるたびに発生するイベントAppDomain.CurrentDomain.AssemblyLoadとイベントにフックすることもできます。AppDomain.CurrentDomain.AssemblyResolve

もう 1 つの重要な点は、 と のバージョン (およびおそらくキー。よくわかりません) が一致している必要がMyAssembly.dllありMyAssembly.XmlSerializers.dll、それらは互いに並べて配置する必要があることです。詳細については、これこの MSDN の記事を参照してください。

于 2011-09-07T20:29:20.153 に答える
1

(まだコメントするのに十分なポイントがありません)

実行時に属性を変更することなく、何をシリアル化し、何をシリアル化しないかを決定できる方法で、弾丸を噛んで IXmlSerializable を実装することを検討する必要があります。独自の属性、コンストラクターの要件を定義し、それらをシリアル化します。

おそらく、XML-Serialization をサックして、そのようなフープをジャンプする必要がほとんどない JSon.Net に切り替えることもできます。

于 2011-09-15T21:43:52.510 に答える