XmlSerializerがコンストラクタでFileNotFoundExceptionを与える


347

タイプをシリアル化しようとすると、以前使用していたアプリケーションが失敗します。

のようなステートメント

XmlSerializer lizer = new XmlSerializer(typeof(MyType));

生成する:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  FusionLog=""
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)

クラスに特別なシリアライザーを定義していません。

この問題を解決するにはどうすればよいですか?


5
OK、それでこの質問は、すでに尋ねられたVB質問の私のC#バージョンです:stackoverflow.com/questions/294659/… ありがとう。
アーウィン

1
6年後の@VladVの答えは、最も単純で、最も悪影響の少ないソリューションです。Generate serialization assemblyドロップダウンを「自動」ではなく「オン」に変更するだけです。
Heliac

@ヘリアック:同意しない。常に機能するとは限りません。Vladの回答に対するBenoit Blanchonのコメントを参照してください。私にとって最も簡単な答えは、設定ファイルでString.Collectionを使用しないことです。代わりに私は使用します:string [] items = Settings.Default.StringofNewlineDelimitedItems.Split(new [] {Environment.NewLine});
Andrew Dennison、2015

回答:


388

信じられないかもしれませんが、これは正常な動作です。例外がスローされますが、XmlSerializerによって処理されるため、それを無視するだけですべてが正常に続行されます。

私はこれが非常に不愉快であることに気づき、少し検索するとこれについて多くの不満がありましたが、私が読んだことから、Microsoftはそれについて何もするつもりはありません。

特定の例外のファーストチャンス例外をオフにすると、デバッグ中に例外ポップアップが常に表示されるのを回避できます。Visual Studioで、デバッグ -> 例外(またはCtrl+ Alt+を押しますE)、共通言語ランタイム例外 -> System.IO- > System.IO.FileNotFoundExceptionに移動します。

別の方法に関する情報は、ブログ投稿C#XmlSerializer FileNotFound例外(Chris CellsのツールXmlSerializerPreCompilerについて説明しています)にあります。


162
この問題を解決する方法の1つは、[ツール]-> [オプション]-> [デバッグ]-> [一般オプション]の[コードのみ]オプションをチェックすることです。
フレデリック

26
@フレデリック:このコメントは素晴らしいです!私はここに「WTF !?」と座っています。私の顔の表現、この偽の例外を突き止めようとしています、そして私はこの質問を答えと共に見つけました(それはMicrosoftのせいです、他に何が新しいのですか?)、しかし私はそれを必要とするかもしれないので例外処理を無効にしたくありませんでした私のコード。A +!
Kumba、2011年

27
以下のハンスの提案の方が価値があると思います。この例外をまったく発生させない別のメソッド呼び出しを使用してください。XmlSerializer serializer = XmlSerializer.FromTypes(new [] {typeof(MyType)})[0];
明るい

3
問題は、これが私のテストに失敗するため、例外を「無視」することはできないということです
Csaba Toth

16
申し訳ありませんが、これはひどい提案です。FileNotFoundExceptionは、私の経験では最も一般的なものの1つであり、この例外レポートを無効にすると、いつか問題が発生する可能性があります。「Just My Code」をオンにするか、以下で説明するシリアル化アセンブリの作成を有効にすることをお勧めします。
Quarkly、2013年

104

マーティンシャーバーンが言ったように、これは正常な動作です。XmlSerializerのコンストラクターは、最初に、[YourAssembly] .XmlSerializers.dllという名前のアセンブリを見つけようとします。これには、タイプのシリアル化用に生成されたクラスが含まれているはずです。このようなDLLはまだ生成されていないため(デフォルトでは生成されていません)、FileNotFoundExceptionがスローされます。これが発生すると、XmlSerializerのコンストラクターがその例外をキャッチし、DLLがXmlSerializerのコンストラクターによって実行時に自動的に生成されます(これは、コンピューターの%temp%ディレクトリにC#ソースファイルを生成し、C#コンパイラを使用してそれらをコンパイルすることによって行われます)。同じタイプのXmlSerializerの追加の構成では、すでに生成されたDLLを使用します。

更新: .NET 4.5以降XmlSerializer、構成ファイルの設定(useLegacySerializerGeneration)を設定して明示的に強制されない限り、実行時にシリアライザーアセンブリを作成するために、コード生成もC#コンパイラーによるコンパイルも実行しなくなりました。この変更により、csc.exe起動時の依存関係がなくなり、起動パフォーマンスが向上します。出典:.NET Framework 4.5 Readme、セクション1.3.8.1。

例外はXmlSerializerのコンストラクターによって処理されます。自分で何もする必要はありません。「続行」(F5)をクリックするだけでプログラムの実行を続行でき、すべてが正常に行われます。プログラムの実行を停止して例外ヘルパーをポップアップする例外に悩まされている場合は、「Just My Code」をオフにするか、「User-」ではなくFileNotFoundExceptionがスローされたときに実行を中断するように設定している未処理」。

「マイコードのみ」を有効にするには、「ツール」→「オプション」→「デバッグ」→「一般」→「マイコードのみを有効にする」に移動します。FileNotFoundがスローされたときに実行の中断をオフにするには、デバッグ>>例外>>検索>> 'FileNotFoundException'と入力します>> System.IO.FileNotFoundExceptionの[Thrown]チェックボックスをオフにします。


更新の+1:これは、テストケースのデバッグ時の異なる動作を説明します
mbx

3
あなたのアップデートは、この例外が.NET 4.5で発生してはならないことを示唆していますが、私はまだそれを見ています。
Timbo

@ティンボ:.NET 4.5でその例外が発生しない理由はわかりません。それでもファイルを探し、ファイルが見つからない場合FileNotFoundExceptionはがスローされます。違いは、アセンブリの存在をチェックする方法ではなく、欠落していると判断されたときにアセンブリを生成する方法です。以前は、C#コンパイラを呼び出してテキストによるC#コード生成を使用してILを作成していました。.NET 4.5以降、コンパイラを使用せずにILを直接出力します。
Allon Guralnek、2015

1
私は、MSがこれを実装するように願っています(File.Exists(...)){Load} else {Fallback} try {Load} catch {Fallback}の代わりに。例外ベースのフロー制御は悪臭を放ち、デバッグ作業を必要以上に難しく、もろくします。
Timbo 2015

1
@ティンボ:単純なFile.Exists()だけでは不十分かもしれません。アセンブリの場所を特定するのは簡単なことではありません。ランタイムはいくつかの場所を検索し、動作は環境(コンソールアプリケーションとIISでホストされているなど)によって変化すると思います。実装されるべきだったのは、TryLoadAssembly()似たようなものだったと思います。
Allon Guralnek、2015

63

Visual Studioプロジェクトのプロパティ(「ビルド」ページ、正しく思い出せば)には、「シリアル化アセンブリを生成する」というオプションがあります。[Containing Assembly of MyType]を生成するプロジェクトでオンにしてみてください。


4
シリアル化アセンブリがVisual Studioによってまだ生成されない場合は、stackoverflow.com / a / 8798289/1164966も参照してください。
Benoit Blanchon 2014

最良の、最も明確で簡潔な答え!また投票したいです!
John Zabroski、2016年

59

そのための回避策があります。使用する場合

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];

その例外を回避する必要があります。これでうまくいきました。

警告: 複数回使用しないでください。使用するとメモリリークが発生します

このメソッドを使用XmlSerializerして同じタイプのインスタンスを複数回作成すると、狂ったようにメモリリークが発生します。

これは、このメソッドがXmlSerializer(type)およびXmlSerializer(type, defaultNameSpace)コンストラクターが提供する組み込みキャッシュをバイパスするためです(他のすべてのコンストラクターもキャッシュをバイパスします)。

これらの2つのコンストラクターを介さないXmlSerializerを作成するためにメソッドを使用する場合は、独自のキャッシュを実装する必要があります。そうしないと、メモリが出血します。


44
警告:このメソッドを使用XmlSerializerして同じタイプのインスタンスを複数回作成すると、狂ったようにメモリリークが発生します。これは、このメソッドがXmlSerializer(type)およびXmlSerializer(type, defaultNameSpace)コンストラクターが提供する組み込みキャッシュをバイパスするためです(他のすべてのコンストラクターもキャッシュをバイパスします)。XmlSerializerこれらの2つのコンストラクタを介さないを作成するメソッドを使用する場合は、独自のキャッシュを実装する必要があります。そうしないと、メモリが出血します。
Allon Guralnek、2012年

4
@AllonGuralnekまあ私はのろわれます...あなたは絶対に正しいです。さらにReflectorを介して掘り下げてみると、キャッシュをチェックする一方で、シリアライゼーションアセンブリの生成後にチェックすることがわかります。WTF?
JerKimball 2013年

4
その既知のバグが判明
JerKimball

3
@JerKimball:そのページは実際には嘘をついていません。あなたが発見FromTypesしたように、キャッシュを埋めているように見えます。したがってXmlSerializer、1つのステートメントで空のキャッシュをウォームアップする有効な方法(記事が示唆するように)である必要がありますが、そこから何かを取得する本当に悪い方法です(最も単純なコンストラクタを介してのみ実行する必要があります)。いずれにせよ、私はそれがバグであることを知りませんでした。リークがあるものはすべてリークするはずだといつも思っていました(より高度なXmlSerializerコンストラクタなど)。FromTypes()あなたがすることができるので、私は使用することさえ考えなかったでしょうtypes.Select(t => new XmlSerializer(t))
Allon Guralnek 2013年

2
@AllonGuralnek使用の非プローブの側面にはFromTypes魅力があります-スローされた例外がすべてキャッチされても、それは高価な操作です。公式にサポートされている唯一の修正は、あいまいなWebベースのアセンブリにあるように見えるため、「独自の方法でキャッシュする」アプローチが唯一の回避策のようです。(編集:率直に言って、私はすべてをデータコントラクトに移植することに全力を
注いでい

22

私はこの正確な問題に遭遇し、言及された解決策のいずれかでそれを回避することができませんでした。

それから私は最終的に解決策を見つけました。シリアライザにはタイプだけでなく、ネストされたタイプも必要なようです。これを変更する:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

これに:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());

私の問題を修正しました。これ以上の例外や何かはありません。


8
これでうまくいきました。.Net4.0を使用した場合の形式はvar xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
user3161729

1
これも私にとってはうまくいきました。ただし、シリアル化する場合にのみ必要であり、逆シリアル化する場合には必要ないようです。多分それは理にかなっているかもしれませんし、多分そうではありません。
SteveCinq 2018

2
何度も実行すると、メモリリークが発生します。
Volodymyr Kotylo

9

私の解決策は、直感的にシリアライザを作成することです。これにより、例外の原因となる奇妙なファイルの読み込みがバイパスされます。これを、シリアライザのキャッシュも処理するヘルパー関数にパッケージ化しました。

private static readonly Dictionary<Type,XmlSerializer> _xmlSerializerCache = new Dictionary<Type, XmlSerializer>();

public static XmlSerializer CreateDefaultXmlSerializer(Type type) 
{
    XmlSerializer serializer;
    if (_xmlSerializerCache.TryGetValue(type, out serializer))
    {
        return serializer;
    }
    else
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(type, null, null);
        serializer = new XmlSerializer(mapping);
        return _xmlSerializerCache[type] = serializer;
    }
}

ここで2つの問題-最初のコードはスレッドセーフではありません。次に(より重要なことに).netランタイムが既に使用しているもの(使用しているctorに基づいて)を複製しようとしています。つまり、このコードの必要はありません
デイブブラック

@DaveBlack:はい、ConcurrentDictionaryへのキャッシングを使用したquadfinityの回答の方が良いでしょう
d--b

@db私の2番目のポイントは、フレームワークがキャッシュする2つのctorの1つを使用している限り(OPが最初のctorを使用している限り)、キャッシュは不要であることです。MSDNから:パフォーマンスを向上させるために、XMLシリアル化インフラストラクチャは動的にアセンブリを生成して、指定された型をシリアル化および逆シリアル化します。フレームワークはそれらのアセンブリを見つけて再利用します。:XmlSerializer.XmlSerializer(タイプ)XmlSerializer.XmlSerializer(タイプ、文字列)参考:この現象は、次のctorsを使用している場合にのみ発生しmsdn.microsoft.com/en-us/library/...
デイブ・ブラック

@DaveBlack:はい。ただし、これらのコンストラクターは、使用法が完全に有効な場合でも、内部で例外をスローしてキャッチします。これは悪いことであり、これがOPがそもそも質問をした理由です。
d--b

@db真実ですが、私が言うつもりでした(しかし、はっきりしていませんでした-私の謝罪)必要なのは、ソルンの唯一の行がelse条件の最初の3行だけであることです。
デイブブラック

8

例外を回避するには、次の2つのことを行う必要があります。

  1. シリアル化されたクラスに属性を追加します(アクセス権があることを願っています)
  2. sgen.exeを使用してシリアル化ファイルを生成する

System.Xml.Serialization.XmlSerializerAssembly属性をクラスに追加します。「MyAssembly」を、MyClassがあるアセンブリの名前に置き換えます。

[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{

}

sgen.exeユーティリティを使用してシリアライゼーションファイルを生成し、クラスのアセンブリでデプロイします。

「sgen.exe MyAssembly.dll」は、MyAssembly.XmlSerializers.dllファイルを生成します

これらの2つの変更により、.netはアセンブリを直接検索します。私はそれをチェックし、それはVisual Studio 2008で.NET Framework 3.5で動作します


さて、これらの変更なしでは失敗しましたか。もしそうなら、なぜですか?
John Saunders、

1
私のプロジェクトVS2012の4.0が突然失敗し始めた理由はわかりません。Active Directoryにアクセスしようとするたびにエラーが発生したため、エラーを「無視」することはできませんでした。したがって、無視すると、認証されなくなります。VS2012がシリアル化DLLを適切に自動生成しないことに、私はまだ非常に苛立っています。ただし、これらの手順は完璧なソリューションを提供しました。
sfuqua 2013

6

この例外は、BindingFailureと呼ばれるマネージデバッグアシスタント(MDA)でもトラップできます。

このMDAは、アプリケーションがビルド済みのシリアル化アセンブリと共に出荷されるように設計されている場合に役立ちます。これは、アプリケーションのパフォーマンスを向上させるために行います。これにより、ビルド済みのシリアライゼーションアセンブリがビルドプロセスによって適切にビルドされ、オンザフライで再ビルドされることなくアプリケーションによってロードされることを確認できます。

他のポスターが述べたように、シリアライザコンストラクターによってバインディングエラーがトラップされると、シリアル化アセンブリは実行時に再構築されるため、このシナリオ以外では実際には役に立ちません。したがって、通常はオフにできます。


6

関数XmlSerializer.FromTypesは例外をスローしませんが、メモリをリークします。そのため、作成されたすべてのインスタンスでメモリリークが発生しないように、このようなシリアライザーをすべてのタイプでキャッシュする必要があります。

独自のXmlSerializerファクトリを作成し、それを簡単に使用します。

XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(MyType));

工場は次のように見えます。

public static class XmlSerializerFactoryNoThrow
{
    public static Dictionary<Type, XmlSerializer> _cache = new Dictionary<Type, XmlSerializer>();

    private static object SyncRootCache = new object();        

    /// <summary>
    /// //the constructor XmlSerializer.FromTypes does not throw exception, but it is said that it causes memory leaks
    /// http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor
    /// That is why I use dictionary to cache the serializers my self.
    /// </summary>
    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            //constructor XmlSerializer.FromTypes does not throw the first chance exception           
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            //serializer = XmlSerializerFactoryNoThrow.Create(type);
        }

        lock (SyncRootCache)
        {
            _cache[type] = serializer;
        }
        return serializer;
    }       
}

メモリリークの可能性のないより複雑なバージョン(誰かがコードを確認してください):

    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            lock (SyncRootCache)
            {
                if (_cache.TryGetValue(type, out serializer))
                    return serializer;
            }
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            lock (SyncRootCache)
            {
                _cache[type] = serializer;
            }
        }          
        return serializer;
    }       
}

代わりにConcurrentDictionaryを使用する必要があります。このコードはデッドロックする可能性があります。
Behrooz 2017年

辞書を使用したすべての管理がロックセクションにある場合、どのようにしてデッドロックになるのでしょうか。
Tomas Kubes 2017年

すみません、言葉が混乱しました。つまり、アイテムを複数回挿入できるということです。存在を確認するときと挿入するときの間にギャップがあるためです。コンカレントディクショナリは、ある種の2フェーズロック(bag [0]、次にbag [hash]])を使用し、作業中のアイテムを挿入/格納する必要があるバッグへの参照を保持します。より速く、より安全で、よりクリーンです。
Behrooz 2017年

はいといいえ。同時に、同じタイプの1つのシリアライザーが2つのスレッドで並列に作成され、その後、辞書に2回追加されるということが起こり得ます。そのような場合、2番目の挿入は最初の挿入を置き換えるだけですが、ロックセクションはスレッドの安全性を保証し、全体的な欠点は小さなメモリリークです。実際のシナリオでは、タイプAのシリアライザを持つスレッド1がタイプBのシリアライザを持つスレッド2によってブロックされることを望まないため、これはパフォーマンスの最適化です。
Tomas Kubes 2017年

解決策は(理論的なメモリリークがなければ)より良いかもしれませんが、より複雑になると想像できます。
Tomas Kubes 2017年

3

一方、コンパイルエラーのトラブルシューティングは非常に複雑です。これらの問題は、次のメッセージとともにFileNotFoundExceptionに現れます。

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
   at System.Reflection.Assembly.nLoad( ... )
   at System.Reflection.Assembly.InternalLoad( ... )
   at System.Reflection.Assembly.Load(...)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() 

file not found例外がシリアライザオブジェクトのインスタンス化とどのように関係しているのか不思議に思うかもしれませんが、コンストラクタはC#ファイルを書き込んでコンパイルしようとします。この例外のコールスタックは、その疑いをサポートするためのいくつかの優れた情報を提供します。XmlSerializerがSystem.Reflection.Assembly.Loadメソッドを呼び出すCodeDOMによって生成されたアセンブリを読み込もうとしたときに例外が発生しました。例外は、XmlSerializerが作成するはずのアセンブリが存在しなかった理由についての説明を提供していません。一般に、アセンブリが存在しないのはコンパイルが失敗したためです。まれに、シリアル化属性によってC#コンパイラがコンパイルに失敗したコードが生成されることが原因である可能性があります。

このエラーは、一時ディレクトリにアクセスできないアカウントまたはセキュリティ環境でXmlSerializerを実行した場合にも発生します。

ソースhttp : //msdn.microsoft.com/en-us/library/aa302290.aspx


彼はこれが実行時に起こることを指定しなかった。もう1つ考えられるのは、おそらく名前空間/クラスの競合があるということです。MyTypeのフルネームは何ですか?
Zyphrax 2009

ええ、私はur linkを調べました。コンストラクタに関する情報は役に立ちましたが、私が必要としていたものではありませんでした。
アーウィン

5
@SpaceghostAl実行時にコンパイルできます。そして、それがXmlSerializerが行うことです。実行時に、特定のタイプのXMLを(逆)シリアル化するアセンブリを動的に構築します。何らかの理由で、このプロセスはOPに失敗します。おそらく一時ディレクトリなどのアクセス許可の問題が原因です。(ディスク領域が足りないほど馬鹿げているかもしれません。)
nos

あなたはこれについて確信を持っていますか?シリアル化の要素は、ビルド時に YourAssemblyName.XmlSerializers.dllという名前のアセンブリにコンパイルされ、実行時にコンパイルされないことはかなり確信していました。これは、さまざまな理由で失敗する可能性があり、少なくとも展開フォルダのすべてのNTFSアクセス許可で失敗する可能性があります。
tomfanning 2009

1
私はこれを何度も賛成できればいいのに。アカウントが一時フォルダにアクセスできないことについてのあなたのメモは私のための答えを引き起こしました。サーバーの管理者グループにサービスアカウントを追加すると、機能しました。ありがとうございました!
ボブ・ホーン

2

Visual Studioプロジェクトプロパティには、「シリアル化アセンブリを生成する」というオプションがあります。[含むMyTypeのアセンブリ]を生成するプロジェクトでオンにしてみてください。


1

シリアル化するカスタムクラス:

[Serializable]
public class TestClass
{
    int x = 2;
    int y = 4;
    public TestClass(){}
    public TestClass(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int TestFunction()
    {
        return x + y;
    }
}

コードスニペットを添付しました。多分これはあなたを助けることができます。

static void Main(string[] args)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));

    MemoryStream memoryStream = new MemoryStream();
    XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

    TestClass domain = new TestClass(10, 3);
    xmlSerializer.Serialize(xmlWriter, domain);
    memoryStream = (MemoryStream)xmlWriter.BaseStream;
    string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray());

    TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString);

    Console.WriteLine(xmlDomain.TestFunction().ToString());
    Console.ReadLine();
}

2
リソースリークを防ぐためにブロックを使用しない場合、およびXmlTextWriterを使用する場合は-1。
John Saunders、

承知しましたが、まだXmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));を使用しています。しかし、私は言われた例外を得ていません。
shahjapan 2009

1

同様の問題があり、例外を無視してもうまくいきませんでした。私のコードはNServiceBusの構成を呼び出していましたConfigure.With(...).XmlSerializer()...

私にとってそれを修正したのは、プロジェクトのプラットフォームを変更することでした。

  1. Build \ Configuration Managerに移動します...
  2. プロジェクトを見つけてプラットフォームを変更します(私の場合はx86から​​Any CPUに)

1

参考として。DBの回答とコメントから、DBソリューションに近いこのソリューションが付属しました。それは私のすべてのケースで正常に動作し、スレッドセーフです。ConcurrentDictionaryを使用しても問題ないと思います。

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace HQ.Util.General
{
    public class XmlSerializerHelper
    {
        private static readonly Dictionary<Type, XmlSerializer> _dictTypeToSerializer = new Dictionary<Type, XmlSerializer>();

        public static XmlSerializer GetSerializer(Type type)
        {
            lock (_dictTypeToSerializer)
            {
                XmlSerializer serializer;
                if (! _dictTypeToSerializer.TryGetValue(type, out serializer))
                {
                    var importer = new XmlReflectionImporter();
                    var mapping = importer.ImportTypeMapping(type, null, null);
                    serializer = new XmlSerializer(mapping);
                    return _dictTypeToSerializer[type] = serializer;
                }

                return serializer;
            }
        }
    }
}

使用法:

        if (File.Exists(Path))
        {
            using (XmlTextReader reader = new XmlTextReader(Path))
            {
                // XmlSerializer x  = new XmlSerializer(typeof(T));
                var x = XmlSerializerHelper.GetSerializer(typeof(T));

                try
                {
                    options = (OptionsBase<T>)x.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    Log.Instance.AddEntry(LogType.LogException, "Unable to open Options file: " + Path, ex);
                }
            }
        }

0

タイプが、GACにもローカルのbinフォルダーにも見つからない他のアセンブリを参照している可能性があります==> ...

「またはその依存関係の1つです。指定されたファイルが見つかりません」

シリアル化するタイプの例を教えてください。

注:タイプがSerializableを実装していることを確認してください。


0

私は同じエラーを受け取りました、そしてそれは私がデシリアライズしようとしていた型がデフォルトのパラメーターのないコンストラクターを持っていなかったためでした。コンストラクタを追加すると、動作し始めました。


0

サードパーティツールを使用してXSDからクラスを生成し、それが機能するまで、同じ問題が発生しました。ツールがクラスの先頭に追加のコードを追加していることを発見しました。これと同じコードを元のクラスの先頭に追加すると、機能しました。これが私が追加したものです...

#pragma warning disable
namespace MyNamespace
{
  using System;
  using System.Diagnostics;
  using System.Xml.Serialization;
  using System.Collections;
  using System.Xml.Schema;
  using System.ComponentModel;
  using System.Xml;
  using System.Collections.Generic;

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
  [System.SerializableAttribute()]
  [System.Diagnostics.DebuggerStepThroughAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
  public partial class MyClassName
  {
  ...

0

を使用するための多くの推奨事項を確認しましたがConcurrentDictionary、その具体例はありません。そのため、このソリューションレースにハットを投入します。私はスレッドセーフな開発者ではないので、このコードがしっかりしていない場合は、フォローしている人のために声を上げてください。

public static class XmlSerializerHelper
{
    private static readonly ConcurrentDictionary<Type, XmlSerializer> TypeSerializers = new ConcurrentDictionary<Type, XmlSerializer>();

    public static XmlSerializer GetSerializer(Type type)
    {
        return TypeSerializers.GetOrAdd(type,
        t =>
        {
            var importer = new XmlReflectionImporter();
            var mapping = importer.ImportTypeMapping(t, null, null);
            return new XmlSerializer(mapping);
        });
    }
}

私が関与する他の記事を見てきましたConcurrentDictionaryし、Lazy値をロードします。それがここに関連しているかどうかはわかりませんが、ここにそのコードがあります:

private static readonly ConcurrentDictionary<Type, Lazy<XmlSerializer>> TypeSerializers = new ConcurrentDictionary<Type, Lazy<XmlSerializer>>();

public static XmlSerializer GetSerializer(Type type)
{
    return TypeSerializers.GetOrAdd(type,
    t =>
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(t, null, null);
        var lazyResult = new Lazy<XmlSerializer>(() => new XmlSerializer(mapping), LazyThreadSafetyMode.ExecutionAndPublication);
        return lazyResult;
    }).Value;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.