Skip to content

Commit 5cc599d

Browse files
committed
DotNetDisassemblerCache.csリファクタリング
1 parent 8dc9f68 commit 5cc599d

1 file changed

Lines changed: 57 additions & 61 deletions

File tree

Services/Caching/DotNetDisassemblerCache.cs

Lines changed: 57 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
34
using System.IO;
45
using System.Linq;
56
using System.Threading.Tasks;
@@ -27,7 +28,7 @@ public static class DotNetDisassemblerCache
2728
/// <summary>
2829
/// 逆アセンブラのバージョン決定に失敗した際のメッセージ(ラベル付き)
2930
/// </summary>
30-
private const string ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION_FOR_LABEL = ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION + " for label:";
31+
private const string ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION_FOR_LABEL = ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION + " for label: '{0}'.";
3132

3233
/// <summary>
3334
/// 逆アセンブラのバージョン決定に失敗した際のメッセージ(無効なラベル)
@@ -82,18 +83,21 @@ private enum DisassemblerKind
8283
/// <exception cref="InvalidOperationException">コマンドラベルが無効、またはバージョン取得に失敗した場合。</exception>
8384
public static async Task<string> GetDisassemblerVersionAsync(string disassembleCommandWithArguments)
8485
{
86+
// 入力の妥当性をまずチェック。空なら即例外。
8587
if (string.IsNullOrWhiteSpace(disassembleCommandWithArguments))
8688
{
8789
throw new InvalidOperationException(ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION_EMPTY);
8890
}
8991

92+
// コマンドから逆アセンブラ種別とキャッシュキー、実行ファイル名を抽出。
9093
var (disassemblerKind, disassemblerVersionCacheKey, disassemblerExe) = GetDisassemblerInfo(disassembleCommandWithArguments);
94+
// 種別に応じてバージョン取得ロジックを切り替え。該当が無ければエラーとして扱う。
9195
return disassemblerKind switch
9296
{
9397
DisassemblerKind.DotnetIldasm => await GetVersionForDotnetIldasmAsync(disassemblerVersionCacheKey, disassemblerExe),
9498
DisassemblerKind.Ildasm => await GetVersionForIldasmAsync(disassemblerVersionCacheKey, disassemblerExe),
9599
DisassemblerKind.Ilspy => await GetVersionForIlspyAsync(disassemblerVersionCacheKey, disassemblerExe),
96-
_ => throw new InvalidOperationException($"{ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION_FOR_LABEL} '{disassembleCommandWithArguments}'.")
100+
_ => throw new InvalidOperationException(string.Format(ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION_FOR_LABEL, disassembleCommandWithArguments))
97101
};
98102
}
99103

@@ -102,12 +106,14 @@ public static async Task<string> GetDisassemblerVersionAsync(string disassembleC
102106
/// </summary>
103107
private static (DisassemblerKind disassemblerKind, string disassemblerVersionCacheKey, string disassemblerExe) GetDisassemblerInfo(string disassembleCommandWithArguments)
104108
{
109+
// コマンド文字列をトークン化し、先頭のコマンド名やラベルを抽出する。
105110
var tokens = Utility.TokenizeCommand(disassembleCommandWithArguments);
106111
if (tokens.Count == 0)
107112
{
108113
throw new InvalidOperationException(string.Format(ERROR_FAILED_TO_DETERMINE_DISASSEMBLER_VERSION_INVALID, disassembleCommandWithArguments));
109114
}
110115

116+
// "dotnet ildasm ..." 形式かどうかを確認。dotnet 経由の場合は muxer を実行ファイルとする。
111117
if (string.Equals(tokens[0], Constants.DOTNET_MUXER, StringComparison.OrdinalIgnoreCase))
112118
{
113119
if (tokens.Count >= 2 && string.Equals(tokens[1], Constants.DOTNET_ILDASM, StringComparison.OrdinalIgnoreCase))
@@ -116,6 +122,7 @@ private static (DisassemblerKind disassemblerKind, string disassemblerVersionCac
116122
}
117123
}
118124

125+
// それ以外は先頭トークンのファイル名で直接判定する。
119126
var exe = tokens[0];
120127
return Path.GetFileName(exe)?.ToLowerInvariant() switch
121128
{
@@ -130,92 +137,81 @@ private static (DisassemblerKind disassemblerKind, string disassemblerVersionCac
130137
/// </summary>
131138
private static async Task<string> GetVersionForDotnetIldasmAsync(string disassemblerVersionCacheKey, string disassemblerExe)
132139
{
133-
var disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [Constants.DOTNET_ILDASM, FLAG_VERSION_LONG]);
134-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
140+
// dotnet-ildasmはサブコマンド付きで --version / -v を順に試す。
141+
var attempts = new (string[] args, bool useFirstLine)[]
135142
{
136-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersion;
137-
return disassemblerVersion;
138-
}
139-
140-
disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [Constants.DOTNET_ILDASM, FLAG_VERSION_SHORT]);
141-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
142-
{
143-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersion;
144-
return disassemblerVersion;
145-
}
146-
147-
if (disassemblerVersionCache.TryGetValue(disassemblerVersionCacheKey, out var cachedDisassemblerVersion))
148-
{
149-
return cachedDisassemblerVersion;
150-
}
151-
152-
throw new InvalidOperationException($"{ERROR_FAILED_TO_GET_VERSION} '{Constants.DOTNET_ILDASM}' ({nameof(disassemblerVersionCacheKey)}='{disassemblerVersionCacheKey}').");
143+
([Constants.DOTNET_ILDASM, FLAG_VERSION_LONG], false),
144+
([Constants.DOTNET_ILDASM, FLAG_VERSION_SHORT], false)
145+
};
146+
return await GetVersionWithFallbacksAsync(disassemblerVersionCacheKey, disassemblerExe, attempts, Constants.DOTNET_ILDASM);
153147
}
154148

155149
/// <summary>
156150
/// ildasm のバージョン情報を取得(キャッシュ)します。
157151
/// </summary>
158152
private static async Task<string> GetVersionForIldasmAsync(string disassemblerVersionCacheKey, string disassemblerExe)
159153
{
160-
var disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [FLAG_VERSION_LONG]);
161-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
162-
{
163-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersion;
164-
return disassemblerVersion;
165-
}
166-
167-
disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [FLAG_VERSION_SHORT]);
168-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
169-
{
170-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersion;
171-
return disassemblerVersion;
172-
}
173-
174-
if (disassemblerVersionCache.TryGetValue(disassemblerVersionCacheKey, out var cachedDisassemblerVersion))
154+
// ildasm は単純に --version と -v の二段構え。
155+
var attempts = new (string[] args, bool useFirstLine)[]
175156
{
176-
return cachedDisassemblerVersion;
177-
}
178-
179-
throw new InvalidOperationException($"{ERROR_FAILED_TO_GET_VERSION} '{Constants.DOTNET_ILDASM}' ({nameof(disassemblerVersionCacheKey)}='{disassemblerVersionCacheKey}').");
157+
([FLAG_VERSION_LONG], false),
158+
([FLAG_VERSION_SHORT], false)
159+
};
160+
return await GetVersionWithFallbacksAsync(disassemblerVersionCacheKey, disassemblerExe, attempts, Constants.DOTNET_ILDASM);
180161
}
181162

182163
/// <summary>
183164
/// ilspycmd のバージョン文字列を取得してキャッシュします(--version/-v/-h の順に試行)。
184165
/// </summary>
185166
private static async Task<string> GetVersionForIlspyAsync(string disassemblerVersionCacheKey, string disassemblerExe)
186167
{
187-
// まずは --version で取得を試みる(成功すればそのままキャッシュ)。
188-
var disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [FLAG_VERSION_LONG]);
189-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
168+
// ilspycmd は --version / -v が失敗する環境向けに -h の先頭行をフォールバックとして使用。
169+
var attempts = new (string[] args, bool useFirstLine)[]
190170
{
191-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersion;
192-
return disassemblerVersion;
193-
}
171+
([FLAG_VERSION_LONG], false),
172+
([FLAG_VERSION_SHORT], false),
173+
([FLAG_HELP_SHORT], true)
174+
};
175+
return await GetVersionWithFallbacksAsync(disassemblerVersionCacheKey, disassemblerExe, attempts, Constants.ILSPY_CMD);
176+
}
194177

195-
// 続いて -v(短縮記法)を試す。
196-
disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [FLAG_VERSION_SHORT]);
197-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
178+
/// <summary>
179+
/// 複数パターンの引数でバージョン取得を試み、成功した結果をキャッシュおよび返却するユーティリティ。
180+
/// </summary>
181+
private static async Task<string> GetVersionWithFallbacksAsync(
182+
string disassemblerVersionCacheKey,
183+
string disassemblerExe,
184+
IEnumerable<(string[] args, bool useFirstLine)> attempts,
185+
string toolName)
186+
{
187+
// 指定された順にバージョン取得の試行を行う。成功した時点で結果を返し、キャッシュにも保存。
188+
foreach (var (args, useFirstLine) in attempts)
198189
{
199-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersion;
200-
return disassemblerVersion;
201-
}
190+
var rawVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, args);
191+
if (string.IsNullOrWhiteSpace(rawVersion))
192+
{
193+
continue;
194+
}
202195

203-
// --version/-v が失敗するケースでは -h 出力の1行目にバージョンが含まれるため fallback する。
204-
disassemblerVersion = await TryGetDisassemblerVersionAsync(disassemblerVersionCacheKey, disassemblerExe, [FLAG_HELP_SHORT]);
205-
if (!string.IsNullOrWhiteSpace(disassemblerVersion))
206-
{
207-
var disassemblerVersionfirstLine = disassemblerVersion.Split('\n').FirstOrDefault()?.Trim();
208-
disassemblerVersionCache[disassemblerVersionCacheKey] = disassemblerVersionfirstLine;
209-
return disassemblerVersionfirstLine;
196+
var processedVersion = useFirstLine
197+
? rawVersion.Split('\n').FirstOrDefault()?.Trim()
198+
: rawVersion;
199+
200+
if (!string.IsNullOrWhiteSpace(processedVersion))
201+
{
202+
disassemblerVersionCache[disassemblerVersionCacheKey] = processedVersion;
203+
return processedVersion;
204+
}
210205
}
211206

207+
// すべて失敗した場合でも、過去に成功した結果が残っていればそちらを返す。
212208
if (disassemblerVersionCache.TryGetValue(disassemblerVersionCacheKey, out var cachedDisassemblerVersion))
213209
{
214210
return cachedDisassemblerVersion;
215211
}
216212

217-
// いずれの方法でも取得できない場合はエラーとして扱う
218-
throw new InvalidOperationException($"{ERROR_FAILED_TO_GET_VERSION} '{Constants.ILSPY_CMD}' ({nameof(disassemblerVersionCacheKey)}='{disassemblerVersionCacheKey}').");
213+
// キャッシュにも存在しない場合は例外を投げて呼び出し元へ通知
214+
throw new InvalidOperationException($"{ERROR_FAILED_TO_GET_VERSION} '{toolName}' ({nameof(disassemblerVersionCacheKey)}='{disassemblerVersionCacheKey}').");
219215
}
220216

221217
/// <summary>

0 commit comments

Comments
 (0)