WeddingThankYou 1.0.0.0
결혼식 이후 감사 인사와 사진, 계좌 안내, 연락처를 모바일 페이지로 전달하는 감사장 서비스입니다.
로딩중...
검색중...
일치하는것 없음
WeddingThankYou.Services.CsvGuestbookStorage 클래스 참조sealed
WeddingThankYou.Services.CsvGuestbookStorage에 대한 상속 다이어그램 :
WeddingThankYou.Services.CsvGuestbookStorage에 대한 협력 다이어그램:

Public 멤버 함수

 CsvGuestbookStorage (IHostEnvironment env)
async Task< IReadOnlyList< GuestbookEntry > > LoadAsync (string slug, CancellationToken ct=default)
async Task SaveAsync (string slug, IReadOnlyList< GuestbookEntry > entries, CancellationToken ct=default)

Private 멤버 함수

string CsvPath (string slug)

정적 Private 멤버 함수

static string Sanitize (string slug)
static bool IsHeader (string line)
static string EscapeCsv (string value)
static List< string > ParseCsvLine (string line)

Private 속성

readonly string _dataDir

정적 Private 속성

static readonly SemaphoreSlim _gate = new(1, 1)

상세한 설명

CsvGuestbookStorage.cs 파일의 21 번째 라인에서 정의되었습니다.

생성자 & 소멸자 문서화

◆ CsvGuestbookStorage()

WeddingThankYou.Services.CsvGuestbookStorage.CsvGuestbookStorage ( IHostEnvironment env)
inline

생성자.

매개변수
env호스트 환경(컨텐츠 루트 경로 계산).

CsvGuestbookStorage.cs 파일의 58 번째 라인에서 정의되었습니다.

59 {
60 _dataDir = Path.Combine(env.ContentRootPath, "App_Data", "Guestbook");
61 Directory.CreateDirectory(_dataDir);
62 }

다음을 참조함 : _dataDir.

멤버 함수 문서화

◆ CsvPath()

string WeddingThankYou.Services.CsvGuestbookStorage.CsvPath ( string slug)
inlineprivate

Csv Path 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
반환값
Csv Path 작업에서 생성한 string 결과입니다.

CsvGuestbookStorage.cs 파일의 88 번째 라인에서 정의되었습니다.

88 =>
89 Path.Combine(_dataDir, $"{Sanitize(slug)}.csv");

다음을 참조함 : _dataDir.

다음에 의해서 참조됨 : LoadAsync(), SaveAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ EscapeCsv()

string WeddingThankYou.Services.CsvGuestbookStorage.EscapeCsv ( string value)
inlinestaticprivate

CSV 필드 이스케이프(RFC4180 준수).

매개변수
value적용할 값입니다.
반환값
Escape Csv 작업에서 생성한 string 결과입니다.

CsvGuestbookStorage.cs 파일의 324 번째 라인에서 정의되었습니다.

325 {
326 value ??= string.Empty;
327 bool needQuote = value.Contains(',') || value.Contains('"') || value.Contains('\n') || value.Contains('\r');
328 if (!needQuote) return value;
329 return $"\"{value.Replace("\"", "\"\"")}\"";
330 }

다음에 의해서 참조됨 : SaveAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ IsHeader()

bool WeddingThankYou.Services.CsvGuestbookStorage.IsHeader ( string line)
inlinestaticprivate

CSV 헤더 여부를 대략 판별합니다.

매개변수
lineline에 사용할 string 값입니다.
반환값
Is Header 조건이 충족되면 true이고, 그렇지 않으면 false입니다.

CsvGuestbookStorage.cs 파일의 294 번째 라인에서 정의되었습니다.

295 {
296 var l = line.Trim().ToLowerInvariant();
297 return l.StartsWith("name,contact,message,createdlocal");
298 }

다음에 의해서 참조됨 : LoadAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ LoadAsync()

async Task< IReadOnlyList< GuestbookEntry > > WeddingThankYou.Services.CsvGuestbookStorage.LoadAsync ( string slug,
CancellationToken ct = default )
inline

Async 데이터를 불러옵니다.

매개변수
slugslug에 사용할 string 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Load Async 작업에서 생성한 Task<IReadOnlyList<GuestbookEntry>> 결과입니다.

WeddingThankYou.Services.IGuestbookStorage를 구현.

CsvGuestbookStorage.cs 파일의 150 번째 라인에서 정의되었습니다.

151 {
152 var csvPath = CsvPath(slug);
153 await _gate.WaitAsync(ct).ConfigureAwait(false);
154 try
155 {
156 var result = new List<GuestbookEntry>();
157 if (!File.Exists(csvPath)) return result;
158
159 using var fs = new FileStream(csvPath, FileMode.Open, FileAccess.Read, FileShare.Read);
160 using var sr = new StreamReader(fs, Encoding.UTF8);
161 string? line;
162
163 // 헤더 지원: 첫 줄이 헤더 같으면 스킵
164 bool first = true;
165 while ((line = await sr.ReadLineAsync().ConfigureAwait(false)) != null)
166 {
167 ct.ThrowIfCancellationRequested();
168 if (string.IsNullOrWhiteSpace(line)) continue;
169
170 if (first && IsHeader(line)) { first = false; continue; }
171 first = false;
172
173 var f = ParseCsvLine(line);
174 if (f.Count < 4) continue;
175
176 if (!DateTime.TryParseExact(f[3], "yyyy-MM-dd HH:mm:ss",
177 CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var when))
178 when = DateTime.Now;
179
180 result.Add(new GuestbookEntry
181 {
182 Name = f[0],
183 Contact = f[1],
184 Message = f[2],
185 CreatedLocal = when
186 });
187 }
188 return result;
189 }
190 finally
191 {
192 _gate.Release();
193 }
194 }

다음을 참조함 : _gate, CsvPath(), IsHeader(), ParseCsvLine().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ ParseCsvLine()

List< string > WeddingThankYou.Services.CsvGuestbookStorage.ParseCsvLine ( string line)
inlinestaticprivate

CSV 한 줄 파싱(따옴표, 이스케이프 처리).

매개변수
lineline에 사용할 string 값입니다.
반환값
Parse Csv Line 작업에서 생성한 List<string> 결과입니다.

CsvGuestbookStorage.cs 파일의 356 번째 라인에서 정의되었습니다.

357 {
358 var list = new List<string>();
359 if (string.IsNullOrEmpty(line)) return list;
360
361 var sb = new StringBuilder();
362 bool inQuotes = false;
363
364 for (int i = 0; i < line.Length; i++)
365 {
366 var ch = line[i];
367 if (inQuotes)
368 {
369 if (ch == '"')
370 {
371 if (i + 1 < line.Length && line[i + 1] == '"')
372 {
373 sb.Append('"'); i++; // "" -> "
374 }
375 else inQuotes = false;
376 }
377 else sb.Append(ch);
378 }
379 else
380 {
381 if (ch == ',') { list.Add(sb.ToString()); sb.Clear(); }
382 else if (ch == '"') inQuotes = true;
383 else sb.Append(ch);
384 }
385 }
386 list.Add(sb.ToString());
387 return list;
388 }

다음에 의해서 참조됨 : LoadAsync().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Sanitize()

string WeddingThankYou.Services.CsvGuestbookStorage.Sanitize ( string slug)
inlinestaticprivate

Sanitize 작업을 수행합니다.

매개변수
slugslug에 사용할 string 값입니다.
반환값
Sanitize 작업에서 생성한 string 결과입니다.

CsvGuestbookStorage.cs 파일의 115 번째 라인에서 정의되었습니다.

115 =>
116 string.Concat((slug ?? string.Empty).ToLowerInvariant().Split(Path.GetInvalidFileNameChars()));

◆ SaveAsync()

async Task WeddingThankYou.Services.CsvGuestbookStorage.SaveAsync ( string slug,
IReadOnlyList< GuestbookEntry > entries,
CancellationToken ct = default )
inline

Async 데이터를 저장합니다.

매개변수
slugslug에 사용할 string 값입니다.
entriesentries에 사용할 IReadOnlyList<GuestbookEntry> 값입니다.
ct취소 요청을 감시하는 토큰입니다.
반환값
Save Async 작업에서 생성한 Task 결과입니다.

WeddingThankYou.Services.IGuestbookStorage를 구현.

CsvGuestbookStorage.cs 파일의 236 번째 라인에서 정의되었습니다.

237 {
238 var csvPath = CsvPath(slug);
239 await _gate.WaitAsync(ct).ConfigureAwait(false);
240 try
241 {
242 var tmp = csvPath + ".tmp";
243 using (var fs = new FileStream(tmp, FileMode.Create, FileAccess.Write, FileShare.None))
244 using (var sw = new StreamWriter(fs, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)))
245 {
246 // 헤더 작성
247 await sw.WriteLineAsync("Name,Contact,Message,CreatedLocal").ConfigureAwait(false);
248
249 foreach (var e in entries)
250 {
251 ct.ThrowIfCancellationRequested();
252 var line = string.Join(",",
253 EscapeCsv(e.Name),
254 EscapeCsv(e.Contact),
255 EscapeCsv(e.Message),
256 EscapeCsv(e.CreatedLocal.ToString("yyyy-MM-dd HH:mm:ss")));
257 await sw.WriteLineAsync(line).ConfigureAwait(false);
258 }
259 }
260
261 File.Copy(tmp, csvPath, overwrite: true);
262 File.Delete(tmp);
263 }
264 finally
265 {
266 _gate.Release();
267 }
268 }

다음을 참조함 : _gate, CsvPath(), EscapeCsv().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

멤버 데이터 문서화

◆ _dataDir

readonly string WeddingThankYou.Services.CsvGuestbookStorage._dataDir
private

data Dir 값을 보관합니다.

CsvGuestbookStorage.cs 파일의 31 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : CsvGuestbookStorage(), CsvPath().

◆ _gate

readonly SemaphoreSlim WeddingThankYou.Services.CsvGuestbookStorage._gate = new(1, 1)
staticprivate

gate 값을 보관합니다.

CsvGuestbookStorage.cs 파일의 40 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : LoadAsync(), SaveAsync().


이 클래스에 대한 문서화 페이지는 다음의 파일로부터 생성되었습니다.: