7

私の Visual Studio 2010 プロジェクトでは、次のビルド後のイベント コマンド ラインを使用して、sgen を使用して XmlSerializers.dll を作成します。

ビルド後イベント:

"$(ProgramFiles)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" /a:"$(TargetPath)" /c:/keyfile:"c:\myproject\mykey.snk" /f

私のプロジェクトには厳密な名前が付けられているため、同じキーを使用して "XmlSerializers.dll" に厳密な名前を付けます。VS は、出力フォルダーに XmlSerializers.dll を作成します。

ただし、ProcessMonitor を使用していることに気付きました。.NET は実行時に CSC.exe を呼び出します。ユーザーが同様の問題を抱えており、XmlSerializer(Type) コンストラクターを使用して解決したこの投稿に出くわしました。

コードで同じ手法を使用しましたが、それでも csc.exe を呼び出します。

var fs = new FileStream(SettingsFilePath, FileMode.Open);
try
{
var serializer = new XmlSerializer(typeof(AppSettings));
settings = (AppSettings)serializer.Deserialize(fs);
}
finally
{
fs.Close();
}

パフォーマンスのために、プリコンパイル済みの XML シリアル化を使用する必要がある理由と、Windows のシャットダウン時に csc.exe エラーが発生することもあります。Windows がシャットダウン シーケンス中に新しいプロセスを開始することを許可しないため、シャットダウン中に Form を閉じたときにアプリケーションがデータを保存します。XMLシリアライゼーションをプリコンパイルすることで、これを回避するための推奨事項を見てきました。

XmlSerializer が sgen によって作成された XmlSerializers.dll を使用しない理由について何か提案はありますか?

ありがとう。

4

3 に答える 3

4

問題は異なるターゲット プラットフォームにある可能性があります。既定でsgenは、'Any CPU' (MSIL) が使用されます。逆シリアル化またはシリアル化される型を含むアセンブリが x86 または x64 用にコンパイルされている場合、.XmlSerializers.dll

より一般的には、シリアル化アセンブリをロードする .NET コードを調べました。ユニット テストと同じ動作を再現するコードを次に示します。

/// <summary>Generates an identifier for the assembly of a specified type</summary>
/// <remarks>Code copied from the .NET serialization classes - to emulate the same bahavior</remarks>
/// <param name="type">The type</param>
/// <returns>String identifying the type's assembly</returns>
static string GenerateAssemblyId(Type type) 
{ 
  Module[] modules = type.Assembly.GetModules();
  ArrayList list = new ArrayList();
  for (int i = 0; i < modules.Length; i++) {
    list.Add(modules[i].ModuleVersionId.ToString()); 
  }
  list.Sort(); 
  StringBuilder sb = new StringBuilder(); 
  for (int i = 0; i < list.Count; i++) {
    sb.Append(list[i].ToString()); 
    sb.Append(",");
  }
  return sb.ToString();
} // GenerateAssemblyId

/// <summary>Verifies that the serialization assembly for the specified type can be loaded</summary>
/// <remarks>Code copied from the .NET serialization classes - to emulate the same behavior and tests</remarks>
/// <param name="type">The type</param>
static void AssertCanLoadXmlSerializers(Type type)
{
  if (type == null)
    throw new ArgumentNullException("type");
  Assembly serializerAssembly = null;
  // Create the name of the XML serilizers assembly from the type's one
  AssemblyName name = type.Assembly.GetName(true); 
  name.Name = name.Name + ".XmlSerializers"; 
  name.CodeBase = null;
  name.CultureInfo = CultureInfo.InvariantCulture;
  try {
    serializerAssembly = Assembly.Load(name);
  } catch (Exception e) {
    Assert.Fail("Unable to load XML serialization assembly for type '{0}': {1}", type.FullName, e.Message);
  }
  object[] attrs = serializerAssembly.GetCustomAttributes(typeof(XmlSerializerVersionAttribute), false);
  if (attrs == null || attrs.Length == 0) {
    Assert.Fail(
      "Unable to use XML serialization assembly '{1}' for type '{0}': it does not contain XmlSerializerVersionAttribute", 
      type.FullName, 
      serializerAssembly.FullName
    );
  }
  if (attrs.Length > 1) {
    Assert.Fail(
      "Unable to use XML serialization assembly '{1}' for type '{0}': it contains multiple XmlSerializerVersionAttribute", 
      type.FullName, 
      serializerAssembly.FullName
    );
  }
  XmlSerializerVersionAttribute assemblyInfo = (XmlSerializerVersionAttribute)attrs[0];
  string assemblyId = GenerateAssemblyId(type);
  if (assemblyInfo.ParentAssemblyId != assemblyId) {
    Assert.Fail(
      "Unable to use XML serialization assembly '{1}' for type '{0}': it does not match assembly id '{2}'", 
      type.FullName, 
      serializerAssembly.FullName,
      assemblyId
    );
  }
} // AssertCanLoadXmlSerializers

AssertCanLoadXmlSerializers()シリアル化/逆シリアル化する必要がある型を渡すだけです。シリアライゼーション アセンブリが読み込まれない場合は、エラー メッセージからその理由がよくわかります。

シリアル化アセンブリが正常であることを合理的に確認できるように、単体テストに追加しました。

于 2012-12-08T02:08:29.277 に答える
0

生成された dll でngen.exeを実行してみましたか?

ランニング

ngen.exe install myproject.XmlSerializers.dll

dll のネイティブ イメージをイメージ キャッシュにインストールします。これは、JIT コンパイラを呼び出すのではなく、実行時に使用する必要があります。

于 2012-05-09T16:16:53.357 に答える
0

シリアル化アセンブリが正しく署名されていることを確認しますか? 通常、引用符をエスケープする必要があります。詳しくはこちらをご覧ください。

ID が一致するかどうかを確認することもできます。シリアル化アセンブリのビルド後にソース アセンブリを変更すると、ID が一致しなくなり、シリアル化アセンブリは使用されなくなります。詳しくはこちらをご覧ください。

すべてが正しい場合: [ツール] -> [オプション] -> [デバッグ] -> [マイ コードのみを有効にする] を無効にし、[デバッグ] -> [例外] -> [共通言語ランタイムの例外] -> [スロー] を有効にします。次に、シリアル化が完了するまでアプリケーションをデバッグします。シリアル化アセンブリを使用できない理由を示す初回例外がスローされます。

于 2013-02-13T07:04:55.033 に答える