초기 커밋: SheetMe 서식생성기 (P0~P5 완료 상태)

레거시 서식생성기(VB.NET WinForms) 대체용 C#/.NET 10 WPF 디자이너.
기준선: 실DB 활성 디자인 1,271건 왕복 의미론 diff 0 / 예외 0, 단위 테스트 49/49.

이 커밋에 함께 포함된 자격증명 분리:
- appsettings.json 을 __HOST__/__PASSWORD__ 플레이스홀더로 전환
- 실접속 정보는 appsettings.Development.json 으로 분리(.gitignore 제외,
  csproj Debug 조건부 복사라 Release 산출물에 실리지 않음)
- ConfigLoader 를 환경변수 > Development > appsettings 순 레이어링으로 변경,
  미치환 플레이스홀더는 '미설정'으로 간주

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-11 17:20:22 +09:00
co-authored by Claude Fable 5
commit 16c07f48dc
102 changed files with 14210 additions and 0 deletions
@@ -0,0 +1,84 @@
namespace SheetMe.Core.Models;
/// <summary>
/// 레거시 서식 XML의 Property 값 변형(variant) 기본형.
/// 레거시 직렬화기(clsBasicDesignerLoader.WriteValue)가 만들어내는 5가지 형태 + 빈 값(Null)을
/// 원형 그대로 보존해 무손실 왕복을 보장한다.
/// </summary>
public abstract class LegacyPropValue
{
/// <summary>텍스트 값 — &lt;Property&gt;text&lt;/Property&gt; (TypeConverter invariant 문자열)</summary>
public sealed class TextValue : LegacyPropValue
{
/// <summary>속성 문자열 값</summary>
public string Value { get; set; } = string.Empty;
public TextValue() { }
public TextValue(string value) => Value = value;
public override LegacyPropValue Clone() => new TextValue(Value);
}
/// <summary>빈 값 — &lt;Property /&gt; 또는 내용 없는 요소 (로더에서 null 로 설정됨)</summary>
public sealed class NullValue : LegacyPropValue
{
public override LegacyPropValue Clone() => new NullValue();
}
/// <summary>중첩 속성 — Content 직렬화 속성의 자식 &lt;Property&gt; 목록 (예: DataBindings)</summary>
public sealed class NestedValue : LegacyPropValue
{
/// <summary>자식 Property 가방</summary>
public PropBag Children { get; set; } = new();
public override LegacyPropValue Clone() => new NestedValue { Children = Children.Clone() };
}
/// <summary>컬렉션 항목 — Content IList 속성의 &lt;Item type="AQN"&gt; 목록 (예: ComboBox Items)</summary>
public sealed class ItemsValue : LegacyPropValue
{
/// <summary>항목 목록</summary>
public List<LegacyItem> Items { get; set; } = new();
public override LegacyPropValue Clone()
{
var clone = new ItemsValue();
foreach (var item in Items)
{
clone.Items.Add(new LegacyItem { Aqn = item.Aqn, Value = item.Value.Clone() });
}
return clone;
}
}
/// <summary>바이너리 값 — &lt;Binary&gt;base64&lt;/Binary&gt; (BinaryFormatter/Byte[] 직렬화 잔재, verbatim 보존)</summary>
public sealed class BinaryValue : LegacyPropValue
{
/// <summary>base64 원문</summary>
public string Base64 { get; set; } = string.Empty;
public override LegacyPropValue Clone() => new BinaryValue { Base64 = Base64 };
}
/// <summary>컴포넌트 참조 — &lt;Reference name="..." /&gt; (같은 호스트 내 사이트 참조)</summary>
public sealed class ReferenceValue : LegacyPropValue
{
/// <summary>참조 대상 컴포넌트 이름</summary>
public string Name { get; set; } = string.Empty;
public override LegacyPropValue Clone() => new ReferenceValue { Name = Name };
}
/// <summary>깊은 복제</summary>
public abstract LegacyPropValue Clone();
}
/// <summary>Content IList 속성의 항목 1개 — &lt;Item type="AQN"&gt;값&lt;/Item&gt;</summary>
public sealed class LegacyItem
{
/// <summary>항목 타입의 AssemblyQualifiedName 원문</summary>
public string Aqn { get; set; } = string.Empty;
/// <summary>항목 값(대개 TextValue)</summary>
public LegacyPropValue Value { get; set; } = new LegacyPropValue.NullValue();
}