67

このコードはFileNotFoundExceptionを生成しますが、最終的には問題なく実行されます。

void ReadXml()
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    //...
}

例外は次のとおりです。


タイプ'System.IO.FileNotFoundException'の最初のチャンスの例外がmscorlib.dllで発生しました

追加情報:ファイルまたはアセンブリ'MyAssembly.XmlSerializers、Version = 1.4.3190.15950、Culture = neutral、PublicKeyToken=null'またはその依存関係の1つを読み込めませんでした。システムは、指定されたファイルを見つけることができません。


シリアル化アセンブリが見つからない場合、フレームワークは自動的にシリアル化アセンブリを生成するようです。 sgen.exeを使用して手動で生成できます。これにより、例外が軽減されます。

Visual StudioでXMLシリアル化アセンブリを自動的に生成するにはどうすればよいですか?


更新:シリアル化アセンブリの生成:オン設定では何も実行されないようです。

4

8 に答える 8

74

Martin が彼の回答で説明したように、SGen タスクが/proxytypessgen.exe コマンド ラインにスイッチを追加しているため、プロジェクト プロパティを使用してシリアライゼーション アセンブリの生成を有効にするだけでは十分ではありません。

Microsoft は、スイッチを無効にして、アセンブリにプロキシ タイプがない場合でも SGen タスクがシリアル化アセンブリを生成できるようにするMSBuild プロパティを文書化しています。/proxytypes

SGenUseProxyTypes

SGen.exe によってプロキシ タイプを生成する必要があるかどうかを示すブール値。SGen ターゲットは、このプロパティを使用して UseProxyTypes フラグを設定します。このプロパティのデフォルトは true で、これを変更する UI はありません。Web サービス以外の型のシリアル化アセンブリを生成するには、このプロパティをプロジェクト ファイルに追加し、Microsoft.Common.Targets または C#/VB.targets をインポートする前に false に設定します。

ドキュメントが示唆しているように、プロジェクト ファイルを手動で変更する必要がありますが、SGenUseProxyTypesプロパティを構成に追加して生成を有効にすることができます。プロジェクト ファイルの構成は、次のようになります。

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>
于 2012-01-10T03:43:51.573 に答える
57

これは、.CSPROJ ファイルの MSBUILD スクリプトを変更することで、どうにかしてそれを実現した方法です。

まず、.CSPROJ ファイルをプロジェクトではなくファイルとして開きます。プロジェクト タグを閉じる直前に、このコメント アウトされたコードが見つかるまで、ファイルの一番下までスクロールします。

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

次のように、独自の AfterBuild ターゲットを挿入して、既存の XmlSerializer と SGen を削除します。

<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
   <!-- Delete the file because I can't figure out how to force the SGen task. -->
   <Delete
     Files="$(TargetDir)$(TargetName).XmlSerializers.dll"
     ContinueOnError="true" />
   <SGen
     BuildAssemblyName="$(TargetFileName)"
     BuildAssemblyPath="$(OutputPath)"
     References="@(ReferencePath)"
     ShouldGenerateSerializer="true"
     UseProxyTypes="false"
     KeyContainer="$(KeyContainerName)"
     KeyFile="$(KeyOriginatorFile)"
     DelaySign="$(DelaySign)"
     ToolPath="$(TargetFrameworkSDKToolsDirectory)"
     Platform="$(Platform)">
      <Output
       TaskParameter="SerializationAssembly"
       ItemName="SerializationAssembly" />
   </SGen>
</Target>

それは私にとってはうまくいきます。

于 2008-10-15T14:45:18.973 に答える
29

この質問に対する他の回答では、[プロジェクト プロパティ] -> [ビルド] -> [シリアル化アセンブリの生成]設定について既に言及されていますが、既定では、プロジェクトに " XML Web サービス プロキシ タイプ"がある場合にのみアセンブリが生成されます。

Visual Studio の正確な動作を理解する最善の方法は、C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727**Microsoft.Common.targets** ファイル内のGenerateSerializationAssembliesターゲットを調べることです。

Visual Studio の [出力]ウィンドウからこのビルド タスクの結果を確認し、 [次からの出力を表示] ドロップダウン ボックスから [ビルド] を選択できます。次の行に沿って何かが表示されるはずです

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\sgen.exe /assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll / proxytypes /reference:.. /compiler:/ delaysign- LibraryA -> D:\Temp\LibraryA\bin\Debug\LibraryA.dll

ここで重要なポイントは、/ proxytypesスイッチです。XML シリアライザー ジェネレーター ツール (Sgen.exe)のさまざまなスイッチについて読むことができます。

MSBuild に精通している場合は、GenerateSerializationAssemblies ターゲットをカスタマイズして、SGen タスクが true ではなく UseProxyTypes="false" の属性を持つようにすることができますが、Visual Studio / MSBuild システムのカスタマイズに関連するすべての責任を負う必要があります。または、ビルド プロセスを拡張して、/proxytypes スイッチを使用せずに手動で SGen を呼び出すこともできます。

SGen のドキュメントを読めば、Microsoft がこの機能の使用を制限したかったことは明らかです。このトピックに関するノイズの量を考えると、Microsoft が Visual Studio エクスペリエンスの文書化で優れた仕事をしなかったことは明らかです。この問題に対するConnect Feedback項目さえありますが、反応は良くありません。

于 2008-11-05T06:20:56.880 に答える
12

新しいsgenタスク定義を作成すると、問題が発生します。タスクを意図したとおりに機能させるために必要な変数を設定するだけです。とにかく、マイクロソフトのドキュメントにはいくつかの重要な情報が欠けています。

シリアル化アセンブリを事前生成する手順

( http://msdn.microsoft.com/en-us/library/ff798449.aspxのパーツを使用)

  1. Visual Studio 2010のソリューションエクスプローラーで、シリアル化アセンブリを生成するプロジェクトを右クリックし、[プロジェクトのアンロード]をクリックします。
  2. ソリューションエクスプローラーで、シリアル化アセンブリを生成するプロジェクトを右クリックし、[。csprojの編集]をクリックします。
  3. .csprojファイルの要素の直後に<TargetFrameworkVersion>v?.?</TargetFrameworkVersion>、次の要素を追加します。

    <SGenUseProxyTypes>false</SGenUseProxyTypes> <SGenPlatformTarget>$(Platform)</SGenPlatformTarget>

  4. .csprojファイル、各プラットフォーム構成

    例えば<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    次の行を追加します。

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. .csprojファイルを保存して閉じます。

  6. ソリューションエクスプローラーで、編集したプロジェクトを右クリックし、[プロジェクトの再読み込み]をクリックします。

この手順により、出力フォルダーに.xmlSerializers.dllという名前の追加のアセンブリが生成されます。このアセンブリをソリューションとともに展開する必要があります。


説明

SGenは、デフォルトではプロキシタイプに対してのみ「任意のCPU」に対して生成されます。これは、プロジェクトファイルで対応する変数を設定しない場合に発生します。

PlatformTargetと一致するには、SGenPlatformTargetが必要です。これはプロジェクトテンプレートのバグだと思う傾向があります。sgenターゲットプラットフォームがプロジェクトのものと異なる必要があるのはなぜですか?その場合、ランタイム例外が発生します

0x80131040:見つかったアセンブリのマニフェスト定義がアセンブリ参照と一致しません

プロジェクトファイルを分析することで、msbuildタスク定義を見つけることができます。

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

ここで、MSBuildToolsPathはhttp://msdn.microsoft.com/en-us/library/bb397428.aspxに依存します<TargetFrameworkVersion>

TargetFrameworkVersion4.0のSGenタスク定義の内部を

Windowsインストールパス\Microsoft.NET\ Framework \ v4.0.30319 \ Microsoft.CSharp.targets

$(SGenPlatformTarget)のような文書化されていない変数を表示するには、プロジェクトファイルで自由に設定できます

<Target
    Name="GenerateSerializationAssemblies"
    Condition="'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
    DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
    Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
    Outputs="$(IntermediateOutputPath)$(_SGenDllName)">

    <SGen
        BuildAssemblyName="$(TargetFileName)"
        BuildAssemblyPath="$(IntermediateOutputPath)"
        References="@(ReferencePath)"
        ShouldGenerateSerializer="$(SGenShouldGenerateSerializer)"
        UseProxyTypes="$(SGenUseProxyTypes)"
        KeyContainer="$(KeyContainerName)"
        KeyFile="$(KeyOriginatorFile)"
        DelaySign="$(DelaySign)"
        ToolPath="$(SGenToolPath)"
        SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
        EnvironmentVariables="$(SGenEnvironment)"
        SerializationAssembly="$(IntermediateOutputPath)$(_SGenDllName)"
        Platform="$(SGenPlatformTarget)"
        Types="$(SGenSerializationTypes)">
            <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
    </SGen>
</Target>
于 2013-03-21T02:06:42.133 に答える
2

パーティーに少し遅れましたが、前の回答は扱いにくいことがわかりました。具体的には、プロジェクトのプロパティを表示しようとすると、Visual Studio がクラッシュしました。これは、csproj ファイルの読み取り方法が理解できなくなったためだと思います。それは言った...

ビルド後のイベント コマンド ラインに次を追加します。

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force

これにより、デバッグまたはリリース用にプロジェクトをビルドするたびに、sgen.exe を直接利用して Xml シリアル化アセンブリを再構築します。

于 2014-08-11T16:01:34.407 に答える
2

以前はすべて正常に動作していたのに、他の誰かが突然この問題に遭遇した場合: 私にとっては、オプション メニュー ([オプション] -> [デバッグ]) で [自分のコードのみを有効にする (管理対象のみ)] チェックボックスがオフになっていることが原因でした (これは以前は.NET Reflector のインストール後に自動的にオフになります)。

編集:もちろん、この例外は以前に発生していましたが、「自分のコードのみを有効にする」がオフの場合、デバッグアシスタント (有効な場合) がスローされると、この時点で停止します。

于 2010-02-14T10:05:09.863 に答える
1

ソリューションのプロパティを確認します。下部の[ビルド]タブには、[シリアル化アセンブリの生成]というドロップダウンがあります。

于 2008-09-25T16:12:58.053 に答える
1

ブレイン バックアップによって提供されるソリューションとは少し異なるソリューションは、次のように使用する必要があるプラットフォーム ターゲットを直接指定することです。

<!-- Check the platform target value and if present use that for a correct *.XmlSerializer.dll platform setup (default is MSIL)-->
<PropertyGroup Condition=" '$(PlatformTarget)'=='' ">
  <SGenPlatform>$(Platform)</SGenPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(PlatformTarget)'!='' ">
  <SGenPlatform>$(PlatformTarget)</SGenPlatform>
</PropertyGroup>

<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
<SGen
  BuildAssemblyName="$(TargetFileName)"
  BuildAssemblyPath="$(OutputPath)"
  References="@(ReferencePath)"
  ShouldGenerateSerializer="true"
  UseProxyTypes="false"
  KeyContainer="$(KeyContainerName)"
  KeyFile="$(KeyOriginatorFile)"
  DelaySign="$(DelaySign)"
  ToolPath="$(SGenToolPath)"
  SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
  EnvironmentVariables="$(SGenEnvironment)"
  Platform="$(SGenPlatform)">
  <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>
于 2014-01-09T09:15:31.340 に答える