Forge
csharp4405de34
1#nullable enable
2using System.Diagnostics.CodeAnalysis;
3using System.Reflection;
4
5namespace CascadeIDE.Services;
6
7/// <summary>
8/// Встроенные копии шипнутых файлов (см. <c>EmbeddedResource</c> в csproj): при отсутствии файла на диске рядом с exe читается ресурс сборки.
9/// Имена ресурсов: <c>CascadeIDE.</c> + относительный путь с <c>/</c> → <c>.</c> (напр. <c>Themes/dark-theme.json</c> → <c>CascadeIDE.Themes.dark-theme.json</c>).
10/// </summary>
11public static class BundledAppContent
12{
13 private static readonly Assembly s_assembly = typeof(BundledAppContent).Assembly;
14 private const string ResourcePrefix = "CascadeIDE.";
15
16 /// <param name="relativePath">Относительно корня приложения, слеши <c>/</c>, напр. <c>UiModes/index.toml</c>.</param>
17 public static bool TryReadEmbeddedText(string relativePath, [NotNullWhen(true)] out string? text)
18 {
19 text = null;
20 var normalized = NormalizeRelative(relativePath);
21 if (normalized.Length == 0)
22 return false;
23 var name = ResourcePrefix + normalized.Replace('/', '.');
24 using var stream = s_assembly.GetManifestResourceStream(name);
25 if (stream is null)
26 return false;
27 using var reader = new StreamReader(stream);
28 text = reader.ReadToEnd();
29 return !string.IsNullOrWhiteSpace(text);
30 }
31
32 /// <summary>Сначала файл под <see cref="AppContext.BaseDirectory"/>, затем встроенный ресурс.</summary>
33 public static bool TryReadDiskThenEmbedded(string relativePath, [NotNullWhen(true)] out string? text)
34 {
35 text = null;
36 var normalized = NormalizeRelative(relativePath);
37 if (normalized.Length == 0)
38 return false;
39 var disk = Path.Combine(AppContext.BaseDirectory, normalized.Replace('/', Path.DirectorySeparatorChar));
40 try
41 {
42 if (File.Exists(disk))
43 {
44 text = File.ReadAllText(disk);
45 return true;
46 }
47 }
48 catch
49 {
50 // fallback на ресурс
51 }
52
53 return TryReadEmbeddedText(normalized, out text);
54 }
55
56 private static string NormalizeRelative(string relativePath) =>
57 relativePath.Replace('\\', '/').TrimStart('/').Trim();
58}
59
View only · write via MCP/CIDE