Dreamine.Web
1.0.0.0
WPF와 Blazor를 한 코드 흐름으로 연결하고 반복적인 MVVM 코드를 줄이는 오픈소스 FullKit 공식 웹 애플리케이션입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
LibraryCatalogSyncService.cs
이 파일의 문서화 페이지로 가기
1
using
System.IO;
2
using
System.Text.RegularExpressions;
3
using
System.Xml.Linq;
4
using
DreamineWeb.Models
;
5
6
namespace
DreamineWeb.Services
;
7
16
public
sealed
class
LibraryCatalogSyncService
17
{
26
private
readonly
ILibraryStore
_store
;
35
private
readonly
string
_libRoot
;
44
private
readonly
string
_xmlDocRoot
;
45
54
private
static
readonly Regex
Whitespace
=
new
(
@"\s+"
, RegexOptions.Compiled);
55
80
public
LibraryCatalogSyncService
(
ILibraryStore
store,
DreamineOptions
opts)
81
{
82
_store
= store;
83
_libRoot
= opts.
LibrarySourceRoot
;
84
_xmlDocRoot
= Path.Combine(AppContext.BaseDirectory,
"wwwroot"
,
"xmldocs"
);
85
}
86
95
public
bool
IsConfigured
=> !
string
.IsNullOrWhiteSpace(
_libRoot
) && Directory.Exists(
_libRoot
);
96
113
public
async Task<LibraryCatalogSyncResult>
SyncAsync
()
114
{
115
if
(!
IsConfigured
)
return
new
LibraryCatalogSyncResult
(-1, 0, 0);
116
117
var projects = Directory.EnumerateFiles(
_libRoot
,
"*.csproj"
, SearchOption.AllDirectories)
118
.Select(
ReadProject
)
119
.Where(p => p is not
null
)
120
.Cast<
ProjectMetadata
>()
121
.Where(p => !p.PackageId.EndsWith(
".Tests"
, StringComparison.OrdinalIgnoreCase))
122
.OrderBy(p =>
CategoryRank
(p.Category))
123
.ThenBy(p => p.PackageId, StringComparer.OrdinalIgnoreCase)
124
.ToList();
125
126
var libraries = await
_store
.GetAllAsync();
127
var byName = libraries.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);
128
var nextSortByCategory = libraries
129
.GroupBy(x =>
string
.IsNullOrWhiteSpace(x.Category) ?
"Other"
: x.Category)
130
.ToDictionary(g => g.Key, g => g.Max(x => x.SortOrder), StringComparer.OrdinalIgnoreCase);
131
132
var added = 0;
133
var updated = 0;
134
135
foreach
(var project
in
projects)
136
{
137
var isNew = !byName.TryGetValue(project.PackageId, out var lib);
138
if
(isNew)
139
{
140
var sortBase = nextSortByCategory.TryGetValue(project.Category, out var current)
141
? current
142
:
CategoryRank
(project.Category) * 10;
143
144
lib =
new
LibraryInfo
145
{
146
Id =
ToId
(project.PackageId),
147
Name = project.PackageId,
148
Category = project.Category,
149
SortOrder = sortBase + 1,
150
IsVisible =
true
,
151
Status =
"stable"
,
152
Version =
"1.0.0"
153
};
154
155
nextSortByCategory[project.Category] = lib.
SortOrder
;
156
added++;
157
}
158
159
if
(
ApplyProjectMetadata
(lib!, project) || isNew)
160
{
161
await
_store
.SaveAsync(lib!);
162
if
(!isNew) updated++;
163
}
164
165
byName[project.PackageId] = lib!;
166
}
167
168
return
new
LibraryCatalogSyncResult
(added, updated, projects.Count);
169
}
170
203
private
bool
ApplyProjectMetadata
(
LibraryInfo
lib,
ProjectMetadata
project)
204
{
205
var dirty =
false
;
206
207
if
(
SetString
(lib.
Name
, project.PackageId, v => lib.
Name
= v ??
string
.Empty)) dirty =
true
;
208
if
(
SetString
(lib.
Category
, project.Category, v => lib.
Category
= v ??
string
.Empty)) dirty =
true
;
209
if
(
SetString
(lib.
Version
, project.Version, v => lib.
Version
= v ??
string
.Empty)) dirty =
true
;
210
if
(
SetString
(lib.
NuGetId
, project.PackageId, v => lib.
NuGetId
= v)) dirty =
true
;
211
if
(
SetString
(lib.
SourceProjectPath
, project.ProjectPath, v => lib.
SourceProjectPath
= v)) dirty =
true
;
212
if
(
SetString
(lib.
TargetFramework
, project.TargetFramework, v => lib.
TargetFramework
= v)) dirty =
true
;
213
214
if
(!
string
.IsNullOrWhiteSpace(project.Description))
215
{
216
if
(
SetString
(lib.
DescriptionEn
, project.Description, v => lib.
DescriptionEn
= v)) dirty =
true
;
217
if
(
string
.IsNullOrWhiteSpace(lib.
Description
))
218
{
219
lib.Description = project.Description;
220
dirty =
true
;
221
}
222
}
223
224
if
(!
string
.IsNullOrWhiteSpace(project.RepositoryUrl))
225
{
226
if
(
SetString
(lib.
RepoUrl
, project.RepositoryUrl, v => lib.
RepoUrl
= v)) dirty =
true
;
227
}
228
229
if
(project.Tags.Length > 0 && !
SameSet
(lib.
Tags
, project.Tags))
230
{
231
lib.Tags = project.Tags;
232
dirty =
true
;
233
}
234
235
if
(!
SameSet
(lib.
Dependencies
, project.Dependencies))
236
{
237
lib.Dependencies = project.Dependencies;
238
dirty =
true
;
239
}
240
241
var xmlPath = Path.Combine(
_xmlDocRoot
, project.PackageId, $
"{project.PackageId}.xml"
);
242
if
(File.Exists(xmlPath))
243
{
244
if
(
SetString
(lib.
XmlDocPath
, xmlPath, v => lib.
XmlDocPath
= v)) dirty =
true
;
245
}
246
247
if
(dirty) lib.UpdatedAt = DateTime.UtcNow;
248
return
dirty;
249
}
250
275
private
static
ProjectMetadata
?
ReadProject
(
string
path)
276
{
277
try
278
{
279
var doc = XDocument.Load(path);
280
var root = doc.Root;
281
if
(root is
null
)
return
null
;
282
283
#pragma warning disable CS1587
310
string
?
Property
(
string
name) => root.Elements(
"PropertyGroup"
)
311
.Elements(name)
312
.Select(x => x.Value.Trim())
313
.FirstOrDefault(x => !
string
.IsNullOrWhiteSpace(x));
314
#pragma warning restore CS1587
315
316
var assemblyName = Path.GetFileNameWithoutExtension(path);
317
var packageId =
Property
(
"PackageId"
) ??
Property
(
"AssemblyName"
) ?? assemblyName;
318
var version =
Property
(
"Version"
);
319
if
(
string
.IsNullOrWhiteSpace(version) || version.Contains(
"$("
, StringComparison.Ordinal))
320
version =
"1.0.0"
;
321
322
var targetFramework =
Property
(
"TargetFramework"
) ??
Property
(
"TargetFrameworks"
) ??
string
.Empty;
323
var description =
Normalize
(
Property
(
"Description"
));
324
var tags =
SplitTags
(
Property
(
"PackageTags"
));
325
var dependencies = root.Elements(
"ItemGroup"
)
326
.Elements(
"ProjectReference"
)
327
.Select(x => x.Attribute(
"Include"
)?.Value)
328
.Where(x => !
string
.IsNullOrWhiteSpace(x))
329
.Select(x => Path.GetFileNameWithoutExtension(x!))
330
.Where(x => !
string
.IsNullOrWhiteSpace(x))
331
.Distinct(StringComparer.OrdinalIgnoreCase)
332
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
333
.ToArray();
334
335
return
new
ProjectMetadata
(
336
path,
337
packageId,
338
version,
339
targetFramework,
340
description,
341
Property
(
"RepositoryUrl"
) ??
Property
(
"PackageProjectUrl"
),
342
tags,
343
dependencies,
344
InferCategory
(packageId));
345
}
346
catch
347
{
348
return
null
;
349
}
350
}
351
376
private
static
string
InferCategory
(
string
packageId)
377
{
378
if
(packageId.StartsWith(
"Dreamine.MVVM."
, StringComparison.OrdinalIgnoreCase))
return
"MVVM"
;
379
if
(packageId.StartsWith(
"Dreamine.UI."
, StringComparison.OrdinalIgnoreCase))
return
"UI"
;
380
if
(packageId.StartsWith(
"Dreamine.Communication."
, StringComparison.OrdinalIgnoreCase))
return
"Communication"
;
381
if
(packageId.StartsWith(
"Dreamine.Database."
, StringComparison.OrdinalIgnoreCase))
return
"Database"
;
382
if
(packageId.StartsWith(
"Dreamine.PLC."
, StringComparison.OrdinalIgnoreCase))
return
"PLC"
;
383
if
(packageId.StartsWith(
"Dreamine.IO."
, StringComparison.OrdinalIgnoreCase))
return
"IO"
;
384
if
(packageId.StartsWith(
"Dreamine.Threading"
, StringComparison.OrdinalIgnoreCase))
return
"Infrastructure"
;
385
if
(packageId.StartsWith(
"Dreamine.Logging"
, StringComparison.OrdinalIgnoreCase))
return
"Infrastructure"
;
386
if
(packageId.StartsWith(
"Dreamine.Hybrid"
, StringComparison.OrdinalIgnoreCase))
return
"Hybrid"
;
387
if
(packageId.StartsWith(
"Dreamine.Identity"
, StringComparison.OrdinalIgnoreCase))
return
"Identity"
;
388
return
"Other"
;
389
}
390
415
private
static
int
CategoryRank
(
string
category) => category
switch
416
{
417
"MVVM"
=> 1,
418
"Hybrid"
=> 2,
419
"UI"
=> 3,
420
"Identity"
=> 4,
421
"Infrastructure"
=> 5,
422
"Database"
=> 6,
423
"Communication"
=> 7,
424
"IO"
=> 8,
425
"PLC"
=> 9,
426
_ => 99
427
};
428
453
private
static
string
ToId
(
string
packageId)
454
{
455
var
id
= packageId.StartsWith(
"Dreamine."
, StringComparison.OrdinalIgnoreCase)
456
? packageId[
"Dreamine."
.Length..]
457
: packageId;
458
459
return
Regex.Replace(
id
.ToLowerInvariant(),
@"[^a-z0-9]+"
,
"-"
).Trim(
'-'
);
460
}
461
486
private
static
string
?
Normalize
(
string
? value)
487
{
488
if
(
string
.IsNullOrWhiteSpace(value))
return
null
;
489
return
Whitespace
.Replace(value.Trim(),
" "
);
490
}
491
516
private
static
string
[]
SplitTags
(
string
? tags) =>
517
string
.IsNullOrWhiteSpace(tags)
518
? []
519
: tags.Split([
';'
,
','
], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
520
.Distinct(StringComparer.OrdinalIgnoreCase)
521
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
522
.ToArray();
523
556
private
static
bool
SameSet
(
string
[] left,
string
[] right) =>
557
left.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
558
.SequenceEqual(right.OrderBy(x => x, StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase);
559
600
private
static
bool
SetString
(
string
? current,
string
? value, Action<string?> assign)
601
{
602
value =
string
.IsNullOrWhiteSpace(value) ? null : value;
603
if
(
string
.Equals(current, value, StringComparison.Ordinal))
return
false
;
604
assign(value);
605
return
true
;
606
}
607
616
private
sealed
record
ProjectMetadata
(
617
string
ProjectPath,
618
string
PackageId,
619
string
Version,
620
string
TargetFramework,
621
string
? Description,
622
string
? RepositoryUrl,
623
string
[] Tags,
624
string
[] Dependencies,
625
string
Category);
626
}
627
636
public
sealed
record
LibraryCatalogSyncResult
(
int
Added,
int
Updated,
int
ScannedProjects);
DreamineWeb.Models
Definition
DocMember.cs:1
DreamineWeb.Models.DocMemberKind.Property
@ Property
Definition
DocMember.cs:41
DreamineWeb.Services
Definition
AdminAuthService.cs:6
DreamineWeb.Services.LibraryCatalogSyncResult
record LibraryCatalogSyncResult(int Added, int Updated, int ScannedProjects)
DreamineWeb.Models.DreamineOptions
Definition
DreamineOptions.cs:14
DreamineWeb.Models.DreamineOptions.LibrarySourceRoot
string LibrarySourceRoot
Definition
DreamineOptions.cs:69
DreamineWeb.Models.LibraryInfo
Definition
LibraryInfo.cs:12
DreamineWeb.Models.LibraryInfo.Name
string Name
Definition
LibraryInfo.cs:30
DreamineWeb.Models.LibraryInfo.NuGetId
string? NuGetId
Definition
LibraryInfo.cs:84
DreamineWeb.Models.LibraryInfo.Version
string Version
Definition
LibraryInfo.cs:75
DreamineWeb.Models.LibraryInfo.SortOrder
int SortOrder
Definition
LibraryInfo.cs:147
DreamineWeb.Models.LibraryInfo.Dependencies
string[] Dependencies
Definition
LibraryInfo.cs:129
DreamineWeb.Models.LibraryInfo.Category
string Category
Definition
LibraryInfo.cs:57
DreamineWeb.Models.LibraryInfo.SourceProjectPath
string? SourceProjectPath
Definition
LibraryInfo.cs:111
DreamineWeb.Models.LibraryInfo.RepoUrl
string? RepoUrl
Definition
LibraryInfo.cs:93
DreamineWeb.Models.LibraryInfo.Description
string Description
Definition
LibraryInfo.cs:39
DreamineWeb.Models.LibraryInfo.Tags
string[] Tags
Definition
LibraryInfo.cs:138
DreamineWeb.Models.LibraryInfo.XmlDocPath
string? XmlDocPath
Definition
LibraryInfo.cs:102
DreamineWeb.Models.LibraryInfo.TargetFramework
string? TargetFramework
Definition
LibraryInfo.cs:120
DreamineWeb.Models.LibraryInfo.DescriptionEn
string? DescriptionEn
Definition
LibraryInfo.cs:48
DreamineWeb.Services.ILibraryStore
Definition
ILibraryStore.cs:14
DreamineWeb.Services.LibraryCatalogSyncService.SameSet
static bool SameSet(string[] left, string[] right)
Definition
LibraryCatalogSyncService.cs:556
DreamineWeb.Services.LibraryCatalogSyncService.SetString
static bool SetString(string? current, string? value, Action< string?> assign)
Definition
LibraryCatalogSyncService.cs:600
DreamineWeb.Services.LibraryCatalogSyncService._store
readonly ILibraryStore _store
Definition
LibraryCatalogSyncService.cs:26
DreamineWeb.Services.LibraryCatalogSyncService.LibraryCatalogSyncService
LibraryCatalogSyncService(ILibraryStore store, DreamineOptions opts)
Definition
LibraryCatalogSyncService.cs:80
DreamineWeb.Services.LibraryCatalogSyncService.ApplyProjectMetadata
bool ApplyProjectMetadata(LibraryInfo lib, ProjectMetadata project)
Definition
LibraryCatalogSyncService.cs:203
DreamineWeb.Services.LibraryCatalogSyncService.ProjectMetadata
record ProjectMetadata(string ProjectPath, string PackageId, string Version, string TargetFramework, string? Description, string? RepositoryUrl, string[] Tags, string[] Dependencies, string Category)
DreamineWeb.Services.LibraryCatalogSyncService.ToId
static string ToId(string packageId)
Definition
LibraryCatalogSyncService.cs:453
DreamineWeb.Services.LibraryCatalogSyncService.SplitTags
static string[] SplitTags(string? tags)
Definition
LibraryCatalogSyncService.cs:516
DreamineWeb.Services.LibraryCatalogSyncService.Normalize
static ? string Normalize(string? value)
Definition
LibraryCatalogSyncService.cs:486
DreamineWeb.Services.LibraryCatalogSyncService.SyncAsync
async Task< LibraryCatalogSyncResult > SyncAsync()
Definition
LibraryCatalogSyncService.cs:113
DreamineWeb.Services.LibraryCatalogSyncService.Whitespace
static readonly Regex Whitespace
Definition
LibraryCatalogSyncService.cs:54
DreamineWeb.Services.LibraryCatalogSyncService._xmlDocRoot
readonly string _xmlDocRoot
Definition
LibraryCatalogSyncService.cs:44
DreamineWeb.Services.LibraryCatalogSyncService.ReadProject
static ? ProjectMetadata ReadProject(string path)
Definition
LibraryCatalogSyncService.cs:275
DreamineWeb.Services.LibraryCatalogSyncService.IsConfigured
bool IsConfigured
Definition
LibraryCatalogSyncService.cs:95
DreamineWeb.Services.LibraryCatalogSyncService._libRoot
readonly string _libRoot
Definition
LibraryCatalogSyncService.cs:35
DreamineWeb.Services.LibraryCatalogSyncService.InferCategory
static string InferCategory(string packageId)
Definition
LibraryCatalogSyncService.cs:376
DreamineWeb.Services.LibraryCatalogSyncService.CategoryRank
static int CategoryRank(string category)
Definition
LibraryCatalogSyncService.cs:415
Services
LibraryCatalogSyncService.cs
다음에 의해 생성됨 :
1.17.0