├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── DesktopClearArhitecture.sln
├── DesktopClearArhitecture.sln.DotSettings
├── Directory.Build.Props
├── LICENSE
├── README.md
├── benchs
└── DesktopClearArchitecture.Infrastructure.Benchs
│ ├── DesktopClearArchitecture.Infrastructure.Benchs.csproj
│ ├── Program.cs
│ └── ServicesBench.cs
├── docker-compose.yml
├── src
├── Application
│ └── DesktopClearArchitecture.Application
│ │ ├── DesktopClearArchitecture.Application.csproj
│ │ ├── Dtos
│ │ └── SongDto.cs
│ │ ├── Extensions
│ │ └── ServiceCollectionExtension.cs
│ │ └── Profiles
│ │ ├── SongProfile.cs
│ │ └── SongRegister.cs
├── Domain
│ └── DesktopClearArchitecture.Domain
│ │ ├── Abstractions
│ │ ├── IGameSearcher.cs
│ │ ├── IMusicPlayer.cs
│ │ └── Repositories
│ │ │ ├── IPagedList.cs
│ │ │ ├── IRepository.cs
│ │ │ ├── IRepositoryFactory.cs
│ │ │ └── IUnitOfWork.cs
│ │ ├── Common
│ │ ├── AuditableEntity.cs
│ │ ├── BaseEntity.cs
│ │ └── Result
│ │ │ ├── PagedList.cs
│ │ │ └── SaveChangesResult.cs
│ │ ├── DesktopClearArchitecture.Domain.csproj
│ │ ├── Entities
│ │ └── Product.cs
│ │ └── Models
│ │ ├── Game.cs
│ │ └── Song.cs
├── Infrastructure
│ ├── DesktopClearArchitecture.Infrastructure.Identity
│ │ └── DesktopClearArchitecture.Infrastructure.Identity.csproj
│ ├── DesktopClearArchitecture.Infrastructure.Persistence
│ │ ├── Configurations
│ │ │ └── ProductConfiguration.cs
│ │ ├── Contexts
│ │ │ └── ApplicationDbContext.cs
│ │ ├── DesktopClearArchitecture.Infrastructure.Persistence.csproj
│ │ ├── Extensions
│ │ │ ├── PagedListExtension.cs
│ │ │ └── ServiceCollectionExtension.cs
│ │ ├── Factories
│ │ │ └── ApplicationDbContextFactory.cs
│ │ └── Repositories
│ │ │ ├── Repository.cs
│ │ │ └── UnitOfWork.cs
│ └── DesktopClearArchitecture.Infrastructure
│ │ ├── DesktopClearArchitecture.Infrastructure.csproj
│ │ ├── Models
│ │ ├── GameList.cs
│ │ └── Root.cs
│ │ └── Services
│ │ ├── GameSearcher.cs
│ │ └── MusicPlayer.cs
└── UI
│ ├── DesktopClearArchitecture.Client
│ ├── App.xaml
│ ├── App.xaml.cs
│ ├── DesktopClearArchitecture.Client.csproj
│ ├── Models
│ │ └── DataNavigationView.cs
│ ├── ViewModels
│ │ └── MainWindowViewModel.cs
│ ├── Views
│ │ ├── MainWindow.xaml
│ │ └── MainWindow.xaml.cs
│ ├── appsettings.Development.json
│ ├── appsettings.Production.json
│ ├── appsettings.Stage.json
│ └── appsettings.json
│ ├── DesktopClearArchitecture.Shared
│ ├── Constants
│ │ └── RegionNames.cs
│ ├── Convertors
│ │ └── CelsiusToFahrenheitConvertor.cs
│ ├── DesktopClearArchitecture.Shared.csproj
│ └── ViewModels
│ │ ├── DialogViewModelBase.cs
│ │ ├── NavigationViewModelBase.cs
│ │ └── ViewModelBase.cs
│ ├── Dialogs
│ └── DesktopClearArchitecture.UI.Dialogs.Authorization
│ │ ├── DesktopClearArchitecture.UI.Dialogs.Authorization.csproj
│ │ ├── ViewModels
│ │ └── AuthorizationControlViewModel.cs
│ │ └── Views
│ │ ├── AuthorizationControl.xaml
│ │ └── AuthorizationControl.xaml.cs
│ └── Modules
│ ├── DesktopClearArchitecture.UI.Modules.Games
│ ├── DesktopClearArchitecture.UI.Modules.Games.csproj
│ ├── GamesModule.cs
│ ├── ViewModels
│ │ └── GamesControlViewModel.cs
│ └── Views
│ │ ├── GamesControl.xaml
│ │ └── GamesControl.xaml.cs
│ ├── DesktopClearArchitecture.UI.Modules.Home
│ ├── DesktopClearArchitecture.UI.Modules.Home.csproj
│ ├── HomeModule.cs
│ ├── ViewModels
│ │ └── HomeControlViewModel.cs
│ └── Views
│ │ ├── HomeControl.xaml
│ │ └── HomeControl.xaml.cs
│ ├── DesktopClearArchitecture.UI.Modules.Music
│ ├── DesktopClearArchitecture.UI.Modules.Music.csproj
│ ├── MusicModule.cs
│ ├── ViewModels
│ │ └── MusicControlViewModel.cs
│ └── Views
│ │ ├── MusicControl.xaml
│ │ └── MusicControl.xaml.cs
│ ├── DesktopClearArchitecture.UI.Modules.Products
│ ├── DesktopClearArchitecture.UI.Modules.Products.csproj
│ ├── ProductsModule.cs
│ ├── ViewModels
│ │ └── ProductsControlViewModel.cs
│ └── Views
│ │ ├── ProductsControl.xaml
│ │ └── ProductsControl.xaml.cs
│ └── DesktopClearArchitecture.UI.Modules.Settings
│ ├── DesktopClearArchitecture.UI.Modules.Settings.csproj
│ ├── SettingsModule.cs
│ ├── ViewModels
│ └── SettingsControlViewModel.cs
│ └── Views
│ ├── SettingsControl.xaml
│ └── SettingsControl.xaml.cs
├── stylecop.ruleset
├── stylecopTests.ruleset
└── tests
├── DesktopClearArchitecture.Architecture.Tests
├── ArchitectureTests.cs
└── DesktopClearArchitecture.Architecture.Tests.csproj
├── DesktopClearArchitecture.Infrasctucture.Identity.Tests
└── DesktopClearArchitecture.Infrasctucture.Identity.Tests.csproj
└── DesktopClearArchitecture.UI.Shared.Tests
├── ConvertorsTests.cs
└── DesktopClearArchitecture.UI.Shared.Tests.csproj
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # This continuous integration pipeline is triggered anytime a user pushes code to the repo.
5 | # This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
6 | name: Wpf Continuous Integration
7 |
8 | # Trigger on every master branch push and pull request
9 | on:
10 | push:
11 | branches:
12 | - master
13 | pull_request:
14 | branches:
15 | - master
16 |
17 | jobs:
18 |
19 | build:
20 |
21 | strategy:
22 | matrix:
23 | targetplatform: [x86, x64]
24 |
25 | runs-on: windows-latest
26 |
27 | env:
28 | App_Packages_Directory: AppPackages
29 | SigningCertificate: GitHubActionsDemo.pfx
30 | Solution_Path: DesktopClearArhitecture.sln
31 | Test_Project_Path: tests\DesktopClearArchitecture.Infrasctucture.Identity.Test\DesktopClearArchitecture.Infrasctucture.Identity.Test.csproj
32 | Wpf_Project_Path: src\UI\DesktopClearArchitecture.Client\DesktopClearArchitecture.Client.csproj
33 | Wap_Project_Directory: MyWpfApp.Package
34 | Wap_Project_Name: MyWpfApp.Package.wapproj
35 | Actions_Allow_Unsecure_Commands: true # Allows AddPAth and SetEnv commands
36 |
37 | steps:
38 | - name: Checkout
39 | uses: actions/checkout@v2
40 | with:
41 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
42 |
43 | # Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv
44 | - name: Use Nerdbank.GitVersioning to set version variables
45 | uses: aarnott/nbgv@v0.3
46 | with:
47 | setAllVars: true
48 |
49 | # Install the .NET Core workload
50 | - name: Install .NET Core
51 | uses: actions/setup-dotnet@v1
52 | with:
53 | dotnet-version: '3.1.302'
54 |
55 | # Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
56 | - name: Setup MSBuild.exe
57 | uses: microsoft/setup-msbuild@v1.0.1
58 |
59 | # Update the version before build
60 | - name: Update manifest version
61 | run: |
62 | [xml]$manifest = get-content ".\$env:Wap_Project_Directory\Package.appxmanifest"
63 | $manifest.Package.Identity.Version = "$env:NBGV_SimpleVersion.0"
64 | $manifest.save(".\$env:Wap_Project_Directory\Package.appxmanifest")
65 |
66 | # Test
67 | - name: Execute Unit Tests
68 | run: dotnet test $env:Test_Project_Path
69 |
70 | # Restore the application
71 | - name: Restore the Wpf application to populate the obj folder
72 | run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
73 | env:
74 | Configuration: Debug
75 | RuntimeIdentifier: win-${{ matrix.targetplatform }}
76 |
77 | # Decode the Base64 encoded Pfx
78 | - name: Decode the Pfx
79 | run: |
80 | $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
81 | $currentDirectory = Get-Location
82 | $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
83 | [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
84 |
85 | # Build the Windows Application Packaging project
86 | - name: Build the Windows Application Packaging Project (wapproj)
87 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
88 | env:
89 | AppxBundle: Never
90 | BuildMode: SideloadOnly
91 | Configuration: Debug
92 | TargetPlatform: ${{ matrix.targetplatform }}
93 |
94 | # Remove the .pfx
95 | - name: Remove the .pfx
96 | run: Remove-Item -path $env:Wap_Project_Directory\$env:SigningCertificate
97 |
98 | # Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact
99 | - name: Upload build artifacts
100 | uses: actions/upload-artifact@v1
101 | with:
102 | name: MSIX Package
103 | path: ${{ env.Wap_Project_Directory }}\${{ env.App_Packages_Directory }}
104 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### VisualStudio template
2 | ## Ignore Visual Studio temporary files, build results, and
3 | ## files generated by popular Visual Studio add-ons.
4 | ##
5 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
6 |
7 | # User-specific files
8 | *.rsuser
9 | *.suo
10 | *.user
11 | *.userosscache
12 | *.sln.docstates
13 |
14 | # User-specific files (MonoDevelop/Xamarin Studio)
15 | *.userprefs
16 |
17 | # Mono auto generated files
18 | mono_crash.*
19 |
20 | # Build results
21 | [Dd]ebug/
22 | [Dd]ebugPublic/
23 | [Rr]elease/
24 | [Rr]eleases/
25 | x64/
26 | x86/
27 | [Ww][Ii][Nn]32/
28 | [Aa][Rr][Mm]/
29 | [Aa][Rr][Mm]64/
30 | bld/
31 | [Bb]in/
32 | [Oo]bj/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
364 |
365 | ### JetBrains template
366 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
367 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
368 |
369 | # User-specific stuff
370 | .idea/**/workspace.xml
371 | .idea/**/tasks.xml
372 | .idea/**/usage.statistics.xml
373 | .idea/**/dictionaries
374 | .idea/**/shelf
375 |
376 | # Generated files
377 | .idea/**/contentModel.xml
378 |
379 | # Sensitive or high-churn files
380 | .idea/**/dataSources/
381 | .idea/**/dataSources.ids
382 | .idea/**/dataSources.local.xml
383 | .idea/**/sqlDataSources.xml
384 | .idea/**/dynamic.xml
385 | .idea/**/uiDesigner.xml
386 | .idea/**/dbnavigator.xml
387 |
388 | # Gradle
389 | .idea/**/gradle.xml
390 | .idea/**/libraries
391 |
392 | # Gradle and Maven with auto-import
393 | # When using Gradle or Maven with auto-import, you should exclude module files,
394 | # since they will be recreated, and may cause churn. Uncomment if using
395 | # auto-import.
396 | # .idea/artifacts
397 | # .idea/compiler.xml
398 | # .idea/jarRepositories.xml
399 | # .idea/modules.xml
400 | # .idea/*.iml
401 | # .idea/modules
402 | # *.iml
403 | # *.ipr
404 |
405 | # CMake
406 | cmake-build-*/
407 |
408 | # Mongo Explorer plugin
409 | .idea/**/mongoSettings.xml
410 |
411 | # File-based project format
412 | *.iws
413 |
414 | # IntelliJ
415 | out/
416 |
417 | # mpeltonen/sbt-idea plugin
418 | .idea_modules/
419 |
420 | # JIRA plugin
421 | atlassian-ide-plugin.xml
422 |
423 | # Cursive Clojure plugin
424 | .idea/replstate.xml
425 |
426 | # Crashlytics plugin (for Android Studio and IntelliJ)
427 | com_crashlytics_export_strings.xml
428 | crashlytics.properties
429 | crashlytics-build.properties
430 | fabric.properties
431 |
432 | # Editor-based Rest Client
433 | .idea/httpRequests
434 |
435 | # Android studio 3.1+ serialized cache file
436 | .idea/caches/build_file_checksums.ser
437 |
438 | ### Windows template
439 | # Windows thumbnail cache files
440 | Thumbs.db
441 | Thumbs.db:encryptable
442 | ehthumbs.db
443 | ehthumbs_vista.db
444 |
445 | # Dump file
446 | *.stackdump
447 |
448 | # Folder config file
449 | [Dd]esktop.ini
450 |
451 | # Recycle Bin used on file shares
452 | $RECYCLE.BIN/
453 |
454 | # Windows Installer files
455 | *.cab
456 | *.msi
457 | *.msix
458 | *.msm
459 | *.msp
460 |
461 | # Windows shortcuts
462 | *.lnk
463 |
464 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | lewshadow@gmail.com.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | If you want to contribute to a project and make it better, your help is very welcome. Contributing is also a great way to learn more about social coding on Github, new technologies and and their ecosystems and how to make constructive, helpful bug reports, feature requests and the noblest of all contributions: a good, clean pull request.
4 |
5 | ### How to make a clean pull request
6 |
7 | Look for a project's contribution instructions. If there are any, follow them.
8 |
9 | - Create a personal fork of the project on Github.
10 | - Clone the fork on your local machine. Your remote repo on Github is called `origin`.
11 | - Add the original repository as a remote called `upstream`.
12 | - If you created your fork a while ago be sure to pull upstream changes into your local repository.
13 | - Create a new branch to work on! Branch from `develop` if it exists, else from `master`.
14 | - Implement/fix your feature, comment your code.
15 | - Follow the code style of the project, including indentation.
16 | - If the project has tests run them!
17 | - Write or adapt tests as needed.
18 | - Add or change the documentation as needed.
19 | - Squash your commits into a single commit with git's [interactive rebase](https://help.github.com/articles/interactive-rebase). Create a new branch if necessary.
20 | - Push your branch to your fork on Github, the remote `origin`.
21 | - From your fork open a pull request in the correct branch. Target the project's `develop` branch if there is one, else go for `master`!
22 | - Once the pull request is approved and merged you can pull the changes from `upstream` to your local repo and delete
23 | your extra branch(es).
24 |
25 | And last but not least: Always write your commit messages in the present tense. Your commit message should describe what the commit, when applied, does to the code – not what you did to the code.
26 |
--------------------------------------------------------------------------------
/DesktopClearArhitecture.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30114.105
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2085163C-7BCB-4625-A63F-AD9EE86FD24F}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C88C0AF8-A3A8-4E2B-BC32-114B411857C0}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{F19B327B-0830-46BF-B041-78ADA2077D64}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{6CB53B6A-C702-4029-BE9A-8CEDB492FA80}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{1BD55B3E-5CF3-4E1C-89B9-AA9C3AE6931E}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solutionFolder", "solutionFolder", "{E5001530-F5A5-480A-8BAD-5487F6069985}"
17 | ProjectSection(SolutionItems) = preProject
18 | .gitignore = .gitignore
19 | README.md = README.md
20 | stylecop.ruleset = stylecop.ruleset
21 | stylecopTests.ruleset = stylecopTests.ruleset
22 | Directory.Build.Props = Directory.Build.Props
23 | EndProjectSection
24 | EndProject
25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Domain", "src\Domain\DesktopClearArchitecture.Domain\DesktopClearArchitecture.Domain.csproj", "{37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}"
26 | EndProject
27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Application", "src\Application\DesktopClearArchitecture.Application\DesktopClearArchitecture.Application.csproj", "{CA84664A-5386-4070-9A72-AC77DB5280AD}"
28 | EndProject
29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Infrastructure", "src\Infrastructure\DesktopClearArchitecture.Infrastructure\DesktopClearArchitecture.Infrastructure.csproj", "{3A2605DB-CCF0-4982-9092-117D6E264E3A}"
30 | EndProject
31 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Infrasctucture.Identity.Tests", "tests\DesktopClearArchitecture.Infrasctucture.Identity.Tests\DesktopClearArchitecture.Infrasctucture.Identity.Tests.csproj", "{03656BAD-7F6A-47D6-BD64-8B788E60EB69}"
32 | EndProject
33 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{02E9CD84-7D81-4943-828D-C7D6DF3C4863}"
34 | EndProject
35 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Infrastructure.Persistence", "src\Infrastructure\DesktopClearArchitecture.Infrastructure.Persistence\DesktopClearArchitecture.Infrastructure.Persistence.csproj", "{6E2F3FF3-2DB3-4914-930E-59987E184A58}"
36 | EndProject
37 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Infrastructure.Identity", "src\Infrastructure\DesktopClearArchitecture.Infrastructure.Identity\DesktopClearArchitecture.Infrastructure.Identity.csproj", "{54D97E45-20DA-4581-BF86-19A52D11DFCC}"
38 | EndProject
39 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Client", "src\UI\DesktopClearArchitecture.Client\DesktopClearArchitecture.Client.csproj", "{CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}"
40 | EndProject
41 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{3F6E1163-17D1-45ED-91FA-6142F89A87BD}"
42 | EndProject
43 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Shared", "src\UI\DesktopClearArchitecture.Shared\DesktopClearArchitecture.Shared.csproj", "{4EEFA1F0-0D10-4943-A281-9E80619BCB1F}"
44 | EndProject
45 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Modules.Home", "src\UI\Modules\DesktopClearArchitecture.UI.Modules.Home\DesktopClearArchitecture.UI.Modules.Home.csproj", "{4A542268-FBE1-4E0D-9EC4-77F64E6739FE}"
46 | EndProject
47 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Modules.Products", "src\UI\Modules\DesktopClearArchitecture.UI.Modules.Products\DesktopClearArchitecture.UI.Modules.Products.csproj", "{C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}"
48 | EndProject
49 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Modules.Music", "src\UI\Modules\DesktopClearArchitecture.UI.Modules.Music\DesktopClearArchitecture.UI.Modules.Music.csproj", "{948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}"
50 | EndProject
51 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Modules.Games", "src\UI\Modules\DesktopClearArchitecture.UI.Modules.Games\DesktopClearArchitecture.UI.Modules.Games.csproj", "{F488DF66-E0F4-4202-917F-00ECDE305644}"
52 | EndProject
53 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Modules.Settings", "src\UI\Modules\DesktopClearArchitecture.UI.Modules.Settings\DesktopClearArchitecture.UI.Modules.Settings.csproj", "{7EAB2162-1DE7-4986-B699-04E67D99B865}"
54 | EndProject
55 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchs", "benchs", "{2A0EDE92-5EF3-456C-A2F3-7F0B3CE11F12}"
56 | EndProject
57 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Infrastructure.Benchs", "benchs\DesktopClearArchitecture.Infrastructure.Benchs\DesktopClearArchitecture.Infrastructure.Benchs.csproj", "{0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}"
58 | EndProject
59 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{41240DE6-89B7-4748-8936-A64108B22FD7}"
60 | ProjectSection(SolutionItems) = preProject
61 | docker-compose.yml = docker-compose.yml
62 | EndProjectSection
63 | EndProject
64 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dialogs", "Dialogs", "{159E30A1-3A11-4E91-84BB-CC4FCFB024B6}"
65 | EndProject
66 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Dialogs.Authorization", "src\UI\Dialogs\DesktopClearArchitecture.UI.Dialogs.Authorization\DesktopClearArchitecture.UI.Dialogs.Authorization.csproj", "{7A199108-9CEF-4326-B8BE-42A9A42161D3}"
67 | EndProject
68 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.UI.Shared.Tests", "tests\DesktopClearArchitecture.UI.Shared.Tests\DesktopClearArchitecture.UI.Shared.Tests.csproj", "{3FD5B281-06EE-4D74-9158-1C7D91FB69C0}"
69 | EndProject
70 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopClearArchitecture.Architecture.Tests", "tests\DesktopClearArchitecture.Architecture.Tests\DesktopClearArchitecture.Architecture.Tests.csproj", "{24A3877F-80BB-4EB2-A921-F8D3E6660EAD}"
71 | EndProject
72 | Global
73 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
74 | Debug|Any CPU = Debug|Any CPU
75 | Debug|x64 = Debug|x64
76 | Debug|x86 = Debug|x86
77 | Release|Any CPU = Release|Any CPU
78 | Release|x64 = Release|x64
79 | Release|x86 = Release|x86
80 | EndGlobalSection
81 | GlobalSection(SolutionProperties) = preSolution
82 | HideSolutionNode = FALSE
83 | EndGlobalSection
84 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
85 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
86 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Debug|Any CPU.Build.0 = Debug|Any CPU
87 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Debug|x64.ActiveCfg = Debug|Any CPU
88 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Debug|x64.Build.0 = Debug|Any CPU
89 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Debug|x86.ActiveCfg = Debug|Any CPU
90 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Debug|x86.Build.0 = Debug|Any CPU
91 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Release|Any CPU.ActiveCfg = Release|Any CPU
92 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Release|Any CPU.Build.0 = Release|Any CPU
93 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Release|x64.ActiveCfg = Release|Any CPU
94 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Release|x64.Build.0 = Release|Any CPU
95 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Release|x86.ActiveCfg = Release|Any CPU
96 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30}.Release|x86.Build.0 = Release|Any CPU
97 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
98 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
99 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Debug|x64.ActiveCfg = Debug|Any CPU
100 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Debug|x64.Build.0 = Debug|Any CPU
101 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Debug|x86.ActiveCfg = Debug|Any CPU
102 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Debug|x86.Build.0 = Debug|Any CPU
103 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
104 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Release|Any CPU.Build.0 = Release|Any CPU
105 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Release|x64.ActiveCfg = Release|Any CPU
106 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Release|x64.Build.0 = Release|Any CPU
107 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Release|x86.ActiveCfg = Release|Any CPU
108 | {CA84664A-5386-4070-9A72-AC77DB5280AD}.Release|x86.Build.0 = Release|Any CPU
109 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
110 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
111 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Debug|x64.ActiveCfg = Debug|Any CPU
112 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Debug|x64.Build.0 = Debug|Any CPU
113 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Debug|x86.ActiveCfg = Debug|Any CPU
114 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Debug|x86.Build.0 = Debug|Any CPU
115 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
116 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Release|Any CPU.Build.0 = Release|Any CPU
117 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Release|x64.ActiveCfg = Release|Any CPU
118 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Release|x64.Build.0 = Release|Any CPU
119 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Release|x86.ActiveCfg = Release|Any CPU
120 | {3A2605DB-CCF0-4982-9092-117D6E264E3A}.Release|x86.Build.0 = Release|Any CPU
121 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
122 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Debug|Any CPU.Build.0 = Debug|Any CPU
123 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Debug|x64.ActiveCfg = Debug|Any CPU
124 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Debug|x64.Build.0 = Debug|Any CPU
125 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Debug|x86.ActiveCfg = Debug|Any CPU
126 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Debug|x86.Build.0 = Debug|Any CPU
127 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Release|Any CPU.ActiveCfg = Release|Any CPU
128 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Release|Any CPU.Build.0 = Release|Any CPU
129 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Release|x64.ActiveCfg = Release|Any CPU
130 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Release|x64.Build.0 = Release|Any CPU
131 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Release|x86.ActiveCfg = Release|Any CPU
132 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69}.Release|x86.Build.0 = Release|Any CPU
133 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
134 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Debug|Any CPU.Build.0 = Debug|Any CPU
135 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Debug|x64.ActiveCfg = Debug|Any CPU
136 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Debug|x64.Build.0 = Debug|Any CPU
137 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Debug|x86.ActiveCfg = Debug|Any CPU
138 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Debug|x86.Build.0 = Debug|Any CPU
139 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Release|Any CPU.ActiveCfg = Release|Any CPU
140 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Release|Any CPU.Build.0 = Release|Any CPU
141 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Release|x64.ActiveCfg = Release|Any CPU
142 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Release|x64.Build.0 = Release|Any CPU
143 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Release|x86.ActiveCfg = Release|Any CPU
144 | {6E2F3FF3-2DB3-4914-930E-59987E184A58}.Release|x86.Build.0 = Release|Any CPU
145 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
146 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
147 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Debug|x64.ActiveCfg = Debug|Any CPU
148 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Debug|x64.Build.0 = Debug|Any CPU
149 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Debug|x86.ActiveCfg = Debug|Any CPU
150 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Debug|x86.Build.0 = Debug|Any CPU
151 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
152 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Release|Any CPU.Build.0 = Release|Any CPU
153 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Release|x64.ActiveCfg = Release|Any CPU
154 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Release|x64.Build.0 = Release|Any CPU
155 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Release|x86.ActiveCfg = Release|Any CPU
156 | {54D97E45-20DA-4581-BF86-19A52D11DFCC}.Release|x86.Build.0 = Release|Any CPU
157 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
158 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Debug|Any CPU.Build.0 = Debug|Any CPU
159 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Debug|x64.ActiveCfg = Debug|Any CPU
160 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Debug|x64.Build.0 = Debug|Any CPU
161 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Debug|x86.ActiveCfg = Debug|Any CPU
162 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Debug|x86.Build.0 = Debug|Any CPU
163 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Release|Any CPU.ActiveCfg = Release|Any CPU
164 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Release|Any CPU.Build.0 = Release|Any CPU
165 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Release|x64.ActiveCfg = Release|Any CPU
166 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Release|x64.Build.0 = Release|Any CPU
167 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Release|x86.ActiveCfg = Release|Any CPU
168 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579}.Release|x86.Build.0 = Release|Any CPU
169 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
170 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
171 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Debug|x64.ActiveCfg = Debug|Any CPU
172 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Debug|x64.Build.0 = Debug|Any CPU
173 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Debug|x86.ActiveCfg = Debug|Any CPU
174 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Debug|x86.Build.0 = Debug|Any CPU
175 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
176 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Release|Any CPU.Build.0 = Release|Any CPU
177 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Release|x64.ActiveCfg = Release|Any CPU
178 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Release|x64.Build.0 = Release|Any CPU
179 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Release|x86.ActiveCfg = Release|Any CPU
180 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F}.Release|x86.Build.0 = Release|Any CPU
181 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
182 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
183 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Debug|x64.ActiveCfg = Debug|Any CPU
184 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Debug|x64.Build.0 = Debug|Any CPU
185 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Debug|x86.ActiveCfg = Debug|Any CPU
186 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Debug|x86.Build.0 = Debug|Any CPU
187 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
188 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Release|Any CPU.Build.0 = Release|Any CPU
189 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Release|x64.ActiveCfg = Release|Any CPU
190 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Release|x64.Build.0 = Release|Any CPU
191 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Release|x86.ActiveCfg = Release|Any CPU
192 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE}.Release|x86.Build.0 = Release|Any CPU
193 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
194 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
195 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Debug|x64.ActiveCfg = Debug|Any CPU
196 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Debug|x64.Build.0 = Debug|Any CPU
197 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Debug|x86.ActiveCfg = Debug|Any CPU
198 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Debug|x86.Build.0 = Debug|Any CPU
199 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
200 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Release|Any CPU.Build.0 = Release|Any CPU
201 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Release|x64.ActiveCfg = Release|Any CPU
202 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Release|x64.Build.0 = Release|Any CPU
203 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Release|x86.ActiveCfg = Release|Any CPU
204 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6}.Release|x86.Build.0 = Release|Any CPU
205 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
206 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
207 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Debug|x64.ActiveCfg = Debug|Any CPU
208 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Debug|x64.Build.0 = Debug|Any CPU
209 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Debug|x86.ActiveCfg = Debug|Any CPU
210 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Debug|x86.Build.0 = Debug|Any CPU
211 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
212 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Release|Any CPU.Build.0 = Release|Any CPU
213 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Release|x64.ActiveCfg = Release|Any CPU
214 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Release|x64.Build.0 = Release|Any CPU
215 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Release|x86.ActiveCfg = Release|Any CPU
216 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5}.Release|x86.Build.0 = Release|Any CPU
217 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
218 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Debug|Any CPU.Build.0 = Debug|Any CPU
219 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Debug|x64.ActiveCfg = Debug|Any CPU
220 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Debug|x64.Build.0 = Debug|Any CPU
221 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Debug|x86.ActiveCfg = Debug|Any CPU
222 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Debug|x86.Build.0 = Debug|Any CPU
223 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Release|Any CPU.ActiveCfg = Release|Any CPU
224 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Release|Any CPU.Build.0 = Release|Any CPU
225 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Release|x64.ActiveCfg = Release|Any CPU
226 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Release|x64.Build.0 = Release|Any CPU
227 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Release|x86.ActiveCfg = Release|Any CPU
228 | {F488DF66-E0F4-4202-917F-00ECDE305644}.Release|x86.Build.0 = Release|Any CPU
229 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
230 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Debug|Any CPU.Build.0 = Debug|Any CPU
231 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Debug|x64.ActiveCfg = Debug|Any CPU
232 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Debug|x64.Build.0 = Debug|Any CPU
233 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Debug|x86.ActiveCfg = Debug|Any CPU
234 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Debug|x86.Build.0 = Debug|Any CPU
235 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Release|Any CPU.ActiveCfg = Release|Any CPU
236 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Release|Any CPU.Build.0 = Release|Any CPU
237 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Release|x64.ActiveCfg = Release|Any CPU
238 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Release|x64.Build.0 = Release|Any CPU
239 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Release|x86.ActiveCfg = Release|Any CPU
240 | {7EAB2162-1DE7-4986-B699-04E67D99B865}.Release|x86.Build.0 = Release|Any CPU
241 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
242 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Debug|Any CPU.Build.0 = Debug|Any CPU
243 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Debug|x64.ActiveCfg = Debug|Any CPU
244 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Debug|x64.Build.0 = Debug|Any CPU
245 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Debug|x86.ActiveCfg = Debug|Any CPU
246 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Debug|x86.Build.0 = Debug|Any CPU
247 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Release|Any CPU.ActiveCfg = Release|Any CPU
248 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Release|Any CPU.Build.0 = Release|Any CPU
249 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Release|x64.ActiveCfg = Release|Any CPU
250 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Release|x64.Build.0 = Release|Any CPU
251 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Release|x86.ActiveCfg = Release|Any CPU
252 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D}.Release|x86.Build.0 = Release|Any CPU
253 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
254 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
255 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Debug|x64.ActiveCfg = Debug|Any CPU
256 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Debug|x64.Build.0 = Debug|Any CPU
257 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Debug|x86.ActiveCfg = Debug|Any CPU
258 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Debug|x86.Build.0 = Debug|Any CPU
259 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
260 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Release|Any CPU.Build.0 = Release|Any CPU
261 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Release|x64.ActiveCfg = Release|Any CPU
262 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Release|x64.Build.0 = Release|Any CPU
263 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Release|x86.ActiveCfg = Release|Any CPU
264 | {7A199108-9CEF-4326-B8BE-42A9A42161D3}.Release|x86.Build.0 = Release|Any CPU
265 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
266 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
267 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Debug|x64.ActiveCfg = Debug|Any CPU
268 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Debug|x64.Build.0 = Debug|Any CPU
269 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Debug|x86.ActiveCfg = Debug|Any CPU
270 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Debug|x86.Build.0 = Debug|Any CPU
271 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
272 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Release|Any CPU.Build.0 = Release|Any CPU
273 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Release|x64.ActiveCfg = Release|Any CPU
274 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Release|x64.Build.0 = Release|Any CPU
275 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Release|x86.ActiveCfg = Release|Any CPU
276 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0}.Release|x86.Build.0 = Release|Any CPU
277 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
278 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
279 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Debug|x64.ActiveCfg = Debug|Any CPU
280 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Debug|x64.Build.0 = Debug|Any CPU
281 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Debug|x86.ActiveCfg = Debug|Any CPU
282 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Debug|x86.Build.0 = Debug|Any CPU
283 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
284 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Release|Any CPU.Build.0 = Release|Any CPU
285 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Release|x64.ActiveCfg = Release|Any CPU
286 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Release|x64.Build.0 = Release|Any CPU
287 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Release|x86.ActiveCfg = Release|Any CPU
288 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD}.Release|x86.Build.0 = Release|Any CPU
289 | EndGlobalSection
290 | GlobalSection(NestedProjects) = preSolution
291 | {F19B327B-0830-46BF-B041-78ADA2077D64} = {2085163C-7BCB-4625-A63F-AD9EE86FD24F}
292 | {6CB53B6A-C702-4029-BE9A-8CEDB492FA80} = {2085163C-7BCB-4625-A63F-AD9EE86FD24F}
293 | {1BD55B3E-5CF3-4E1C-89B9-AA9C3AE6931E} = {2085163C-7BCB-4625-A63F-AD9EE86FD24F}
294 | {37B48BD7-CB1F-47F0-99C0-0FA7486D8D30} = {F19B327B-0830-46BF-B041-78ADA2077D64}
295 | {CA84664A-5386-4070-9A72-AC77DB5280AD} = {1BD55B3E-5CF3-4E1C-89B9-AA9C3AE6931E}
296 | {3A2605DB-CCF0-4982-9092-117D6E264E3A} = {6CB53B6A-C702-4029-BE9A-8CEDB492FA80}
297 | {03656BAD-7F6A-47D6-BD64-8B788E60EB69} = {C88C0AF8-A3A8-4E2B-BC32-114B411857C0}
298 | {02E9CD84-7D81-4943-828D-C7D6DF3C4863} = {2085163C-7BCB-4625-A63F-AD9EE86FD24F}
299 | {6E2F3FF3-2DB3-4914-930E-59987E184A58} = {6CB53B6A-C702-4029-BE9A-8CEDB492FA80}
300 | {54D97E45-20DA-4581-BF86-19A52D11DFCC} = {6CB53B6A-C702-4029-BE9A-8CEDB492FA80}
301 | {CCE55E0F-1DB5-4B71-AE9C-93E11B9F9579} = {02E9CD84-7D81-4943-828D-C7D6DF3C4863}
302 | {3F6E1163-17D1-45ED-91FA-6142F89A87BD} = {02E9CD84-7D81-4943-828D-C7D6DF3C4863}
303 | {4EEFA1F0-0D10-4943-A281-9E80619BCB1F} = {02E9CD84-7D81-4943-828D-C7D6DF3C4863}
304 | {4A542268-FBE1-4E0D-9EC4-77F64E6739FE} = {3F6E1163-17D1-45ED-91FA-6142F89A87BD}
305 | {C020FDA8-FE2B-4FC6-8944-4070ED51EDC6} = {3F6E1163-17D1-45ED-91FA-6142F89A87BD}
306 | {948EB0DA-668C-43B4-BFA7-0DAC4FAEF2F5} = {3F6E1163-17D1-45ED-91FA-6142F89A87BD}
307 | {F488DF66-E0F4-4202-917F-00ECDE305644} = {3F6E1163-17D1-45ED-91FA-6142F89A87BD}
308 | {7EAB2162-1DE7-4986-B699-04E67D99B865} = {3F6E1163-17D1-45ED-91FA-6142F89A87BD}
309 | {0C0FB20D-B1E6-432F-B7CD-40E7D3DF300D} = {2A0EDE92-5EF3-456C-A2F3-7F0B3CE11F12}
310 | {159E30A1-3A11-4E91-84BB-CC4FCFB024B6} = {02E9CD84-7D81-4943-828D-C7D6DF3C4863}
311 | {7A199108-9CEF-4326-B8BE-42A9A42161D3} = {159E30A1-3A11-4E91-84BB-CC4FCFB024B6}
312 | {3FD5B281-06EE-4D74-9158-1C7D91FB69C0} = {C88C0AF8-A3A8-4E2B-BC32-114B411857C0}
313 | {24A3877F-80BB-4EB2-A921-F8D3E6660EAD} = {C88C0AF8-A3A8-4E2B-BC32-114B411857C0}
314 | EndGlobalSection
315 | EndGlobal
316 |
--------------------------------------------------------------------------------
/DesktopClearArhitecture.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
3 | True
4 | True
5 | True
6 | True
7 | True
8 | True
9 | True
10 | True
11 | True
12 | True
--------------------------------------------------------------------------------
/Directory.Build.Props:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0-windows
4 | preview
5 | x64
6 | false
7 | ..\..\..\stylecop.ruleset
8 | true
9 | NU1701
10 | enable
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 |
18 |
19 |
20 |
21 | none
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Georgy Levchenko
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WPF Clear Architecture Template.
2 |
3 | ## About The Project :zap:
4 |
5 | This repository is a template for building desktop applications based on a clean architecture.
6 |
7 | ## Solving common problems.
8 |
9 | * Clean application architecture.
10 | * Easy navigation (thanks to the use of NavigationView and the Prism modules).
11 | * Simple filtering and commands (Reactive Property).
12 | * Support for many extensions for IServiceCollection (AddLogging(), AddDbContex(), AddMemoryCache()).
13 |
14 | ## Tech Stack :muscle:
15 |
16 | * [WPF .NET6](https://docs.microsoft.com/ru-ru/dotnet/desktop/wpf/?view=netdesktop-6.0)
17 | * [Prism](https://prismlibrary.com/)
18 | * [ReactiveProperty](https://github.com/runceel/ReactiveProperty)
19 | * [Entity Framework Core 6](https://docs.microsoft.com/en-us/ef/core/)
20 | * [AutoMapper](https://automapper.org/)
21 | * [FluentValidation](https://fluentvalidation.net/)
22 | * [Serilog](https://serilog.net/)
23 | * [XUnit](https://xunit.net/), [FluentAssertions](https://fluentassertions.com/), [Moq](https://github.com/moq)
24 | * [Docker](https://www.docker.com/)
25 |
26 | ## Down the Roadmap
27 |
28 | * Add MediatoR
29 | * Add architectural tests
30 |
31 | ## Contributing
32 |
33 | Contributions are what make the open-source community such an amazing place to be, learn, inspire, and create. Any contributions you make are **greatly appreciated**.
34 |
35 | 1. Fork the Project
36 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
37 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
38 | 4. Push to the Branch (`git push origin feature/AmazingFeature`)
39 | 5. Open a Pull Request
40 |
41 | ## Special thanks to
42 |
43 | [](https://www.jetbrains.com/?from=DesktopClearArchitecture)
44 |
45 | ## License
46 |
47 | Distributed under the MIT License.
48 |
49 | ## Contact
50 | ### Georgy Levchenko
51 |
52 | -
53 | - Telegram - [Georgy Levchenko](https://t.me/foxtes)
54 |
55 | ## Support :star:
56 |
57 | Has this Project helped you learn something New? or Helped you at work? Do Consider Supporting.
58 | Here are a few ways by which you can support.
59 |
60 | - Recommend this awesome project to your colleagues. 🥇
61 | - Leave your feedback
62 |
63 |
--------------------------------------------------------------------------------
/benchs/DesktopClearArchitecture.Infrastructure.Benchs/DesktopClearArchitecture.Infrastructure.Benchs.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | ..\..\stylecopTests.ruleset
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/benchs/DesktopClearArchitecture.Infrastructure.Benchs/Program.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Benchs;
2 |
3 | using BenchmarkDotNet.Running;
4 |
5 | ///
6 | /// Main.
7 | ///
8 | public static class Program
9 | {
10 | private static void Main()
11 | {
12 | BenchmarkRunner.Run();
13 | }
14 | }
--------------------------------------------------------------------------------
/benchs/DesktopClearArchitecture.Infrastructure.Benchs/ServicesBench.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Benchs;
2 |
3 | using AutoMapper;
4 | using Application.Dtos;
5 | using DesktopClearArchitecture.Domain.Models;
6 | using FastExpressionCompiler;
7 | using Mapster;
8 | using BenchmarkDotNet.Attributes;
9 | using Services;
10 |
11 | ///
12 | /// Bench for .
13 | ///
14 | [MemoryDiagnoser]
15 | public class ServicesBench
16 | {
17 | private readonly Mapper _mapper;
18 | private readonly MusicPlayer _musicPlayer;
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | public ServicesBench()
24 | {
25 | _musicPlayer = new MusicPlayer();
26 |
27 | var config = new MapperConfiguration(cfg => cfg.CreateMap()
28 | .ForMember(dest => dest.FullName, opt => opt.MapFrom(scr => $"{scr.Name} - {scr.Duration.ToString()}")));
29 | _mapper = new Mapper(config);
30 |
31 | TypeAdapterConfig
32 | .ForType()
33 | .Map(dest => dest.FullName, scr => $"{scr.Name} - {scr.Duration.ToString()}");
34 | TypeAdapterConfig.GlobalSettings.Compiler = exp => exp.CompileFast();
35 | }
36 |
37 | ///
38 | /// Get songs.
39 | ///
40 | [Benchmark]
41 | public void GetSongs()
42 | {
43 | _ = _musicPlayer
44 | .GetSongs()
45 | .ToArray();
46 | }
47 |
48 | ///
49 | /// Get songs.
50 | ///
51 | [Benchmark]
52 | public void GetAutomaper()
53 | {
54 | var songs = _musicPlayer
55 | .GetSongs()
56 | .ToArray();
57 | _ = _mapper.Map(songs);
58 | }
59 |
60 | ///
61 | /// Get songs.
62 | ///
63 | [Benchmark]
64 | public void GetSongsMapster()
65 | {
66 | var songs = _musicPlayer
67 | .GetSongs()
68 | .ToArray();
69 | _ = songs.Adapt();
70 | }
71 | }
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.9"
2 |
3 | seq-input-gelf:
4 | image: datalust/seq-input-gelf:latest
5 | depends_on:
6 | - seq
7 | ports:
8 | - "12201:12201/udp"
9 | environment:
10 | SEQ_ADDRESS: "http://seq:5342"
11 | restart: unless-stopped
12 |
13 | seq:
14 | image: datalust/seq:latest
15 | ports:
16 | - "5342:80"
17 | environment:
18 | ACCEPT_EULA: Y
19 | restart: unless-stopped
20 | volumes:
21 | - ./seq-data:/data
22 |
23 | elasticsearch:
24 | image: docker.elastic.co/elasticsearch/elasticsearch:7.4.2
25 | environment:
26 | - discovery.type=single-node
27 | - bootstrap.memory_lock=true
28 | - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
29 | ports:
30 | - "9200:9200"
31 | networks:
32 | - "elk-net"
33 |
34 | kibana:
35 | image: docker.elastic.co/kibana/kibana:7.4.2
36 | ports:
37 | - "5601:5601"
38 | networks:
39 | - "elk-net"
40 |
41 | networks:
42 | elk-net:
--------------------------------------------------------------------------------
/src/Application/DesktopClearArchitecture.Application/DesktopClearArchitecture.Application.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Application/DesktopClearArchitecture.Application/Dtos/SongDto.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Application.Dtos;
2 |
3 | ///
4 | /// Song dto.
5 | ///
6 | public readonly record struct SongDto
7 | {
8 | ///
9 | /// Full name song.
10 | ///
11 | public string FullName { get; init; }
12 |
13 | ///
14 | public override string ToString() => FullName;
15 | }
--------------------------------------------------------------------------------
/src/Application/DesktopClearArchitecture.Application/Extensions/ServiceCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Application.Extensions;
2 |
3 | using System.Reflection;
4 | using FastExpressionCompiler;
5 | using Mapster;
6 | using Microsoft.Extensions.DependencyInjection;
7 |
8 | ///
9 | /// Extension for .
10 | ///
11 | public static class ServiceCollectionExtension
12 | {
13 | ///
14 | /// Added automapper.
15 | ///
16 | /// .
17 | public static IServiceCollection AddAutomapper(this IServiceCollection services)
18 | {
19 | services.AddAutoMapper(Assembly.GetExecutingAssembly());
20 |
21 | return services;
22 | }
23 |
24 | ///
25 | /// Added mapster.
26 | ///
27 | /// .
28 | public static IServiceCollection AddMapster(this IServiceCollection services)
29 | {
30 | TypeAdapterConfig.GlobalSettings.Compiler = exp => exp.CompileFast();
31 | TypeAdapterConfig.GlobalSettings.Scan(Assembly.GetExecutingAssembly());
32 |
33 | return services;
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Application/DesktopClearArchitecture.Application/Profiles/SongProfile.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Application.Profiles;
2 |
3 | using AutoMapper;
4 | using Domain.Models;
5 | using Dtos;
6 |
7 | ///
8 | /// Song profile.
9 | ///
10 | public class SongProfile : Profile
11 | {
12 | ///
13 | public SongProfile()
14 | {
15 | CreateMap()
16 | .ForMember(dest => dest.FullName, opt => opt.MapFrom(scr => $"{scr.Name} - {scr.Duration.ToString()}"));
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/DesktopClearArchitecture.Application/Profiles/SongRegister.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Application.Profiles;
2 |
3 | using Domain.Models;
4 | using Dtos;
5 | using Mapster;
6 |
7 | ///
8 | /// Song register.
9 | ///
10 | public class SongRegister : IRegister
11 | {
12 | ///
13 | public void Register(TypeAdapterConfig config)
14 | {
15 | config.ForType()
16 | .Map(dest => dest.FullName, scr => $"{scr.Name} - {scr.Duration.ToString()}");
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Abstractions/IGameSearcher.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Abstractions;
2 |
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 | using Models;
6 |
7 | ///
8 | /// Game searcher.
9 | ///
10 | public interface IGameSearcher
11 | {
12 | ///
13 | /// Get all game on steam platform.
14 | ///
15 | Task> GetGames();
16 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Abstractions/IMusicPlayer.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Abstractions;
2 |
3 | using System.Collections.Generic;
4 | using Models;
5 |
6 | ///
7 | /// Music player.
8 | ///
9 | public interface IMusicPlayer
10 | {
11 | ///
12 | /// Get all songs.
13 | ///
14 | IEnumerable GetSongs();
15 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Abstractions/Repositories/IPagedList.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Abstractions.Repositories;
2 |
3 | ///
4 | /// Provides the interface(s) for paged list of any type.
5 | ///
6 | /// The type for paging.
7 | public interface IPagedList
8 | {
9 | ///
10 | /// Gets the index start value.
11 | ///
12 | /// The index start value.
13 | int IndexFrom { get; }
14 |
15 | ///
16 | /// Gets the page index (current).
17 | ///
18 | int PageIndex { get; }
19 |
20 | ///
21 | /// Gets the page size.
22 | ///
23 | int PageSize { get; }
24 |
25 | ///
26 | /// Gets the total count of the list of type .
27 | ///
28 | int TotalCount { get; }
29 |
30 | ///
31 | /// Gets the total pages.
32 | ///
33 | int TotalPages { get; }
34 |
35 | ///
36 | /// Gets the current page items.
37 | ///
38 | IList Items { get; }
39 |
40 | ///
41 | /// Gets the has previous page.
42 | ///
43 | /// The has previous page.
44 | bool HasPreviousPage { get; }
45 |
46 | ///
47 | /// Gets the has next page.
48 | ///
49 | /// The has next page.
50 | bool HasNextPage { get; }
51 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Abstractions/Repositories/IRepositoryFactory.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Abstractions.Repositories;
2 |
3 | ///
4 | /// Defines the interfaces for interfaces.
5 | ///
6 | public interface IRepositoryFactory
7 | {
8 | ///
9 | /// Gets the specified repository for the .
10 | ///
11 | /// True if providing custom repository.
12 | /// The type of the entity.
13 | /// An instance of type inherited from interface.
14 | IRepository GetRepository(bool hasCustomRepository = false)
15 | where TEntity : class;
16 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Abstractions/Repositories/IUnitOfWork.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Abstractions.Repositories;
2 |
3 | using Common.Result;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.ChangeTracking;
6 | using Microsoft.EntityFrameworkCore.Storage;
7 |
8 | ///
9 | /// Defines the interface(s) for generic unit of work.
10 | ///
11 | public interface IUnitOfWork : IUnitOfWork
12 | where TContext : DbContext
13 | {
14 | ///
15 | /// Gets the db context.
16 | ///
17 | /// The instance of type .
18 | TContext DbContext { get; }
19 |
20 | ///
21 | /// Saves all changes made in this context to the database with distributed transaction.
22 | ///
23 | /// An optional array.
24 | /// A that represents the asynchronous save operation.
25 | /// The task result contains the number of state entities written to database.
26 | Task SaveChangesAsync(params IUnitOfWork[] unitOfWorks);
27 | }
28 |
29 | ///
30 | /// Defines the interface(s) for unit of work.
31 | ///
32 | public interface IUnitOfWork : IDisposable
33 | {
34 | ///
35 | /// Last error after SaveChanges operation executed.
36 | ///
37 | SaveChangesResult LastSaveChangesResult { get; }
38 |
39 | ///
40 | /// Gets the specified repository for the .
41 | ///
42 | /// True if providing custom repository.
43 | /// The type of the entity.
44 | /// An instance of type inherited from interface.
45 | IRepository GetRepository(bool hasCustomRepository = false)
46 | where TEntity : class;
47 |
48 | ///
49 | /// Saves all changes made in this context to the database.
50 | ///
51 | /// The number of state entries written to the database.
52 | int SaveChanges();
53 |
54 | ///
55 | /// Asynchronously saves all changes made in this unit of work to the database.
56 | ///
57 | /// A that represents the asynchronous save operation.
58 | /// The task result contains the number of state entities written to database.
59 | Task SaveChangesAsync();
60 |
61 | ///
62 | /// Executes the specified raw SQL command.
63 | ///
64 | /// The raw SQL.
65 | /// The parameters.
66 | /// The number of state entities written to database.
67 | int ExecuteSqlCommand(string sql, params object[] parameters);
68 |
69 | ///
70 | /// Executes the specified raw SQL command.
71 | ///
72 | /// The raw SQL.
73 | /// The parameters.
74 | /// The number of state entities written to database.
75 | Task ExecuteSqlCommandAsync(string sql, params object[] parameters);
76 |
77 | ///
78 | /// Uses raw SQL queries to fetch the specified data.
79 | ///
80 | /// The type of the entity.
81 | /// The raw SQL.
82 | /// The parameters.
83 | /// An that contains elements that satisfy
84 | /// the condition specified by raw SQL.
85 | IQueryable FromSqlRaw(string sql, params object[] parameters)
86 | where TEntity : class;
87 |
88 | ///
89 | /// Uses Track Graph Api to attach disconnected entities.
90 | ///
91 | /// Root entity.
92 | /// Delegate to convert Object's State properties to Entities entry state.
93 | void TrackGraph(object rootEntity, Action callback);
94 |
95 | ///
96 | /// Begin transaction.
97 | ///
98 | /// Use if exist.
99 | Task BeginTransactionAsync(bool useIfExists = false);
100 |
101 | ///
102 | /// Begin transaction async.
103 | ///
104 | /// Use if exist.
105 | IDbContextTransaction BeginTransaction(bool useIfExists = false);
106 |
107 | ///
108 | /// DbContext disable/enable auto detect changes.
109 | ///
110 | /// Value.
111 | void SetAutoDetectChanges(bool value);
112 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Common/AuditableEntity.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Common;
2 |
3 | using System;
4 |
5 | ///
6 | /// Auditable entity.
7 | ///
8 | public abstract class AuditableEntity : BaseEntity
9 | {
10 | ///
11 | /// Create by.
12 | ///
13 | public string CreatedBy { get; set; }
14 |
15 | ///
16 | /// Data created.
17 | ///
18 | public DateTime Created { get; set; }
19 |
20 | ///
21 | /// Last modified by.
22 | ///
23 | public string LastModifiedBy { get; set; }
24 |
25 | ///
26 | /// Data last modified.
27 | ///
28 | public DateTime? LastModified { get; set; }
29 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Common/BaseEntity.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Common;
2 |
3 | ///
4 | /// Base entity.
5 | ///
6 | public abstract class BaseEntity
7 | {
8 | ///
9 | /// Id.
10 | ///
11 | public virtual long Id { get; set; }
12 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Common/Result/PagedList.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Common.Result;
2 |
3 | using Abstractions.Repositories;
4 |
5 | ///
6 | /// Provides the implementation of the and converter.
7 | ///
8 | /// The type of the source.
9 | /// The type of the result.
10 | public record PagedList : IPagedList
11 | {
12 | ///
13 | /// Initializes a new instance of the class.
14 | ///
15 | /// The source.
16 | /// The converter.
17 | /// The index of the page.
18 | /// The size of the page.
19 | /// The index from.
20 | public PagedList(
21 | IEnumerable source,
22 | Func, IEnumerable> converter,
23 | int pageIndex,
24 | int pageSize,
25 | int indexFrom)
26 | {
27 | if (indexFrom > pageIndex)
28 | {
29 | throw new ArgumentException(
30 | $"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
31 | }
32 |
33 | if (source is IQueryable queryable)
34 | {
35 | PageIndex = pageIndex;
36 | PageSize = pageSize;
37 | IndexFrom = indexFrom;
38 | TotalCount = queryable.Count();
39 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
40 |
41 | var items = queryable
42 | .Skip((PageIndex - IndexFrom) * PageSize)
43 | .Take(PageSize)
44 | .ToArray();
45 |
46 | Items = new List(converter(items));
47 | }
48 | else
49 | {
50 | var enumerable = source as TSource[] ?? source.ToArray();
51 |
52 | PageIndex = pageIndex;
53 | PageSize = pageSize;
54 | IndexFrom = indexFrom;
55 | TotalCount = enumerable.Length;
56 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
57 |
58 | var items = enumerable
59 | .Skip((PageIndex - IndexFrom) * PageSize)
60 | .Take(PageSize)
61 | .ToArray();
62 |
63 | Items = new List(converter(items));
64 | }
65 | }
66 |
67 | ///
68 | /// Initializes a new instance of the class.
69 | ///
70 | /// The source.
71 | /// The converter.
72 | public PagedList(IPagedList source, Func, IEnumerable> converter)
73 | {
74 | PageIndex = source.PageIndex;
75 | PageSize = source.PageSize;
76 | IndexFrom = source.IndexFrom;
77 | TotalCount = source.TotalCount;
78 | TotalPages = source.TotalPages;
79 |
80 | Items = new List(converter(source.Items));
81 | }
82 |
83 | ///
84 | public int PageIndex { get; }
85 |
86 | ///
87 | public int PageSize { get; }
88 |
89 | ///
90 | public int TotalCount { get; }
91 |
92 | ///
93 | public int TotalPages { get; }
94 |
95 | ///
96 | public int IndexFrom { get; }
97 |
98 | ///
99 | public IList Items { get; }
100 |
101 | ///
102 | public bool HasPreviousPage => PageIndex - IndexFrom > 0;
103 |
104 | ///
105 | public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;
106 |
107 | ///
108 | /// Creates an empty of .
109 | ///
110 | /// The type for paging.
111 | /// An empty instance of .
112 | public static IPagedList Empty() => new PagedList();
113 | }
114 |
115 | ///
116 | /// Represents the default implementation of the interface.
117 | ///
118 | /// The type of the data to page.
119 | public record PagedList : IPagedList
120 | {
121 | ///
122 | /// Initializes a new instance of the class.
123 | ///
124 | /// The source.
125 | /// The index of the page.
126 | /// The size of the page.
127 | /// The index from.
128 | public PagedList(IEnumerable source, int pageIndex, int pageSize, int indexFrom)
129 | {
130 | if (indexFrom > pageIndex)
131 | {
132 | throw new ArgumentException(
133 | $"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
134 | }
135 |
136 | if (source is IQueryable queryable)
137 | {
138 | PageIndex = pageIndex;
139 | PageSize = pageSize;
140 | IndexFrom = indexFrom;
141 | TotalCount = queryable.Count();
142 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
143 | Items = queryable
144 | .Skip((PageIndex - IndexFrom) * PageSize)
145 | .Take(PageSize)
146 | .ToList();
147 | }
148 | else
149 | {
150 | var enumerable = source.ToList();
151 |
152 | PageIndex = pageIndex;
153 | PageSize = pageSize;
154 | IndexFrom = indexFrom;
155 | TotalCount = enumerable.Count;
156 | TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
157 | Items = enumerable
158 | .Skip((PageIndex - IndexFrom) * PageSize)
159 | .Take(PageSize)
160 | .ToList();
161 | }
162 | }
163 |
164 | ///
165 | /// Initializes a new instance of the class.
166 | ///
167 | public PagedList() => Items = Array.Empty();
168 |
169 | ///
170 | public int PageIndex { get; init; }
171 |
172 | ///
173 | public int PageSize { get; init; }
174 |
175 | ///
176 | public int TotalCount { get; init; }
177 |
178 | ///
179 | public int TotalPages { get; init; }
180 |
181 | ///
182 | public int IndexFrom { get; init; }
183 |
184 | ///
185 | public IList Items { get; init; }
186 |
187 | ///
188 | public bool HasPreviousPage => PageIndex - IndexFrom > 0;
189 |
190 | ///
191 | public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;
192 |
193 | ///
194 | /// Creates a new instance of from source of instance.
195 | ///
196 | /// The type of the result.
197 | /// The type of the source.
198 | /// The source.
199 | /// The converter.
200 | /// An instance of .
201 | public static IPagedList From(
202 | IPagedList source,
203 | Func, IEnumerable> converter) =>
204 | new PagedList(source, converter);
205 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Common/Result/SaveChangesResult.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 |
3 | namespace DesktopClearArchitecture.Domain.Common.Result;
4 |
5 | ///
6 | /// Represent operation result for SaveChanges.
7 | ///
8 | public class SaveChangesResult
9 | {
10 | ///
11 | /// Initializes a new instance of the class.
12 | ///
13 | public SaveChangesResult() => Messages = new List();
14 |
15 | ///
16 | public SaveChangesResult(string message)
17 | : this() => AddMessage(message);
18 |
19 | ///
20 | /// Is Exception occupied while last operation execution.
21 | ///
22 | public bool IsOk => Exception == null;
23 |
24 | ///
25 | /// Last Exception you can find here.
26 | ///
27 | public Exception? Exception { get; set; }
28 |
29 | ///
30 | /// List of the error should appear there.
31 | ///
32 | private List Messages { get; }
33 |
34 | ///
35 | /// Adds new message to result.
36 | ///
37 | /// Message.
38 | public void AddMessage(string message) => Messages.Add(message);
39 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/DesktopClearArchitecture.Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Entities/Product.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Entities;
2 |
3 | using Common;
4 |
5 | ///
6 | /// Product.
7 | ///
8 | public class Product : AuditableEntity
9 | {
10 | ///
11 | /// Name.
12 | ///
13 | public string Name { get; set; }
14 |
15 | ///
16 | public override string ToString() => Name;
17 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Models/Game.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Models;
2 |
3 | using System.Runtime.Serialization;
4 |
5 | ///
6 | /// Song.
7 | ///
8 | public readonly record struct Game
9 | {
10 | ///
11 | /// Name.
12 | ///
13 | [DataMember(Name = "appid")]
14 | public int Id { get; init; }
15 |
16 | ///
17 | /// Duration.
18 | ///
19 | [DataMember(Name = "name")]
20 | public string Name { get; init; }
21 | }
--------------------------------------------------------------------------------
/src/Domain/DesktopClearArchitecture.Domain/Models/Song.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Domain.Models;
2 |
3 | ///
4 | /// Song.
5 | ///
6 | public readonly record struct Song
7 | {
8 | ///
9 | /// Name.
10 | ///
11 | public string Name { get; init; }
12 |
13 | ///
14 | /// Duration.
15 | ///
16 | public int Duration { get; init; }
17 | }
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Identity/DesktopClearArchitecture.Infrastructure.Identity.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/Configurations/ProductConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Persistence.Configurations
2 | {
3 | using Bogus;
4 | using Domain.Entities;
5 | using Microsoft.EntityFrameworkCore;
6 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
7 |
8 | ///
9 | public class ProductConfiguration : IEntityTypeConfiguration
10 | {
11 | ///
12 | public void Configure(EntityTypeBuilder builder)
13 | {
14 | builder.ToTable("Product");
15 |
16 | var ids = 1;
17 | var stock = new Faker()
18 | .RuleFor(m => m.Id, _ => ids++)
19 | .RuleFor(m => m.Created, _ => DateTime.Now)
20 | .RuleFor(m => m.Name, f => f.Commerce.ProductName());
21 | builder.HasData(stock.GenerateBetween(10, 100));
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Persistence.Contexts
2 | {
3 | using Configurations;
4 | using Domain.Entities;
5 | using Microsoft.EntityFrameworkCore;
6 |
7 | ///
8 | public class ApplicationDbContext : DbContext
9 | {
10 | ///
11 | public ApplicationDbContext(DbContextOptions options)
12 | : base(options)
13 | {
14 | }
15 |
16 | ///
17 | /// Products.
18 | ///
19 | public DbSet Products { get; set; }
20 |
21 | ///
22 | protected override void OnModelCreating(ModelBuilder modelBuilder)
23 | {
24 | modelBuilder.ApplyConfigurationsFromAssembly(typeof(ProductConfiguration).Assembly);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/DesktopClearArchitecture.Infrastructure.Persistence.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | all
7 | runtime; build; native; contentfiles; analyzers; buildtransitive
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/Extensions/PagedListExtension.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Persistence.Extensions;
2 |
3 | using DesktopClearArchitecture.Domain.Abstractions.Repositories;
4 | using Domain.Common.Result;
5 | using Microsoft.EntityFrameworkCore;
6 |
7 | ///
8 | /// Provides some extension methods for to provide paging capability.
9 | ///
10 | public static class PagedListExtension
11 | {
12 | ///
13 | /// Converts the specified source to
14 | /// by the specified and .
15 | ///
16 | /// The type of the source.
17 | /// The source to paging.
18 | /// The index of the page.
19 | /// The size of the page.
20 | /// The start index value.
21 | /// An instance of the inherited from interface.
22 | public static IPagedList ToPagedList(
23 | this IEnumerable source,
24 | int pageIndex,
25 | int pageSize,
26 | int indexFrom = 0)
27 | {
28 | return new PagedList(source, pageIndex, pageSize, indexFrom);
29 | }
30 |
31 | ///
32 | /// Converts the specified source to
33 | /// by the specified , and .
34 | ///
35 | /// The type of the source.
36 | /// The type of the result.
37 | /// The source to convert.
38 | ///
39 | /// The converter to change the to .
40 | ///
41 | /// The page index.
42 | /// The page size.
43 | /// The start index value.
44 | /// An instance of the inherited from interface.
45 | public static IPagedList ToPagedList(
46 | this IEnumerable source,
47 | Func, IEnumerable> converter,
48 | int pageIndex,
49 | int pageSize,
50 | int indexFrom = 0)
51 | {
52 | return new PagedList(source, converter, pageIndex, pageSize, indexFrom);
53 | }
54 |
55 | ///
56 | /// Converts the specified source to
57 | /// by the specified and .
58 | ///
59 | /// The type of the source.
60 | /// The source to paging.
61 | /// The index of the page.
62 | /// The size of the page.
63 | /// The start index value.
64 | ///
65 | /// A to observe while waiting for the task to complete.
66 | ///
67 | /// An instance of the inherited from interface.
68 | public static async Task> ToPagedListAsync(
69 | this IQueryable source,
70 | int pageIndex,
71 | int pageSize,
72 | int indexFrom = 0,
73 | CancellationToken cancellationToken = default)
74 | {
75 | if (indexFrom > pageIndex)
76 | {
77 | throw new ArgumentException(
78 | $"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
79 | }
80 |
81 | var count = await source
82 | .CountAsync(cancellationToken)
83 | .ConfigureAwait(false);
84 | var items = await source
85 | .Skip((pageIndex - indexFrom) * pageSize)
86 | .Take(pageSize)
87 | .ToListAsync(cancellationToken)
88 | .ConfigureAwait(false);
89 |
90 | var pagedList = new PagedList
91 | {
92 | PageIndex = pageIndex,
93 | PageSize = pageSize,
94 | IndexFrom = indexFrom,
95 | TotalCount = count,
96 | Items = items,
97 | TotalPages = (int)Math.Ceiling(count / (double)pageSize)
98 | };
99 |
100 | return pagedList;
101 | }
102 | }
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/Extensions/ServiceCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Persistence.Extensions
2 | {
3 | using Contexts;
4 | using Domain.Abstractions.Repositories;
5 | using Microsoft.EntityFrameworkCore;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.DependencyInjection;
8 | using Microsoft.Extensions.Logging;
9 | using Repositories;
10 | using Serilog;
11 |
12 | ///
13 | /// Extension for .
14 | ///
15 | public static class ServiceCollectionExtension
16 | {
17 | ///
18 | /// Added persistence.
19 | ///
20 | /// .
21 | /// .
22 | public static IServiceCollection AddPersistence(this IServiceCollection services, IConfiguration configuration)
23 | {
24 | if (configuration.GetValue("UseInMemoryDatabase"))
25 | {
26 | services.AddDbContext(options =>
27 | options.UseInMemoryDatabase("ApplicationDb"));
28 | }
29 | else
30 | {
31 | services.AddDbContext(options =>
32 | options
33 | .UseSqlite(
34 | configuration.GetConnectionString("DefaultConnection"),
35 | b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName))
36 | .LogTo(Log.Logger.Information, LogLevel.Information));
37 | }
38 |
39 | return services;
40 | }
41 |
42 | ///
43 | /// Added migrations database.
44 | ///
45 | /// .
46 | public static IServiceCollection AddMigrationsDatabase(this IServiceCollection services)
47 | {
48 | var serviceProvider = services.BuildServiceProvider();
49 | var service = serviceProvider.GetRequiredService();
50 |
51 | service.Database.Migrate();
52 | return services;
53 | }
54 |
55 | ///
56 | /// Registers the unit of work given context as a service in the .
57 | ///
58 | /// The type of the db context.
59 | /// The to add services to.
60 | /// The same service collection so that multiple calls can be chained.
61 | ///
62 | /// This method only support one db context, if been called more than once, will throw exception.
63 | ///
64 | public static IServiceCollection AddUnitOfWork(this IServiceCollection services)
65 | where TContext : DbContext
66 | {
67 | services.AddScoped>();
68 | services.AddScoped>();
69 | services.AddScoped, UnitOfWork>();
70 |
71 | return services;
72 | }
73 |
74 | ///
75 | /// Registers the unit of work given context as a service in the .
76 | ///
77 | /// The type of the db context.
78 | /// The type of the db context2.
79 | /// The to add services to.
80 | /// The same service collection so that multiple calls can be chained.
81 | ///
82 | /// This method only support one db context, if been called more than once, will throw exception.
83 | ///
84 | public static IServiceCollection AddUnitOfWork(this IServiceCollection services)
85 | where TContext1 : DbContext
86 | where TContext2 : DbContext
87 | {
88 | services.AddScoped, UnitOfWork>();
89 | services.AddScoped, UnitOfWork>();
90 |
91 | return services;
92 | }
93 |
94 | ///
95 | /// Registers the unit of work given context as a service in the .
96 | ///
97 | /// The type of the db context.
98 | /// The type of the db context2.
99 | /// The type of the db context3.
100 | /// The to add services to.
101 | /// The same service collection so that multiple calls can be chained.
102 | ///
103 | /// This method only support one db context, if been called more than once, will throw exception.
104 | ///
105 | public static IServiceCollection AddUnitOfWork(
106 | this IServiceCollection services)
107 | where TContext1 : DbContext
108 | where TContext2 : DbContext
109 | where TContext3 : DbContext
110 | {
111 | services.AddScoped, UnitOfWork>();
112 | services.AddScoped, UnitOfWork>();
113 | services.AddScoped, UnitOfWork>();
114 |
115 | return services;
116 | }
117 |
118 | ///
119 | /// Registers the unit of work given context as a service in the .
120 | ///
121 | /// The type of the db context.
122 | /// The type of the db context2.
123 | /// The type of the db context3.
124 | /// The type of the db context4.
125 | /// The to add services to.
126 | /// The same service collection so that multiple calls can be chained.
127 | ///
128 | /// This method only support one db context, if been called more than once, will throw exception.
129 | ///
130 | public static IServiceCollection AddUnitOfWork(
131 | this IServiceCollection services)
132 | where TContext1 : DbContext
133 | where TContext2 : DbContext
134 | where TContext3 : DbContext
135 | where TContext4 : DbContext
136 | {
137 | services.AddScoped, UnitOfWork>();
138 | services.AddScoped, UnitOfWork>();
139 | services.AddScoped, UnitOfWork>();
140 | services.AddScoped, UnitOfWork>();
141 |
142 | return services;
143 | }
144 |
145 | ///
146 | /// Registers the custom repository as a service in the .
147 | ///
148 | /// The type of the entity.
149 | /// The type of the custom repository.
150 | /// The to add services to.
151 | /// The same service collection so that multiple calls can be chained.
152 | public static IServiceCollection AddCustomRepository(this IServiceCollection services)
153 | where TEntity : class
154 | where TRepository : class, IRepository
155 | {
156 | services.AddScoped, TRepository>();
157 |
158 | return services;
159 | }
160 | }
161 | }
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/Factories/ApplicationDbContextFactory.cs:
--------------------------------------------------------------------------------
1 | namespace DesktopClearArchitecture.Infrastructure.Persistence.Factories;
2 |
3 | using Contexts;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Design;
6 | using Microsoft.Extensions.Configuration;
7 |
8 | ///
9 | public class ApplicationDbContextFactory : IDesignTimeDbContextFactory
10 | {
11 | ///
12 | public ApplicationDbContext CreateDbContext(string[] args)
13 | {
14 | var currentEnvironment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Development";
15 | var configuration = new ConfigurationBuilder()
16 | .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../../UI/DesktopClearArchitecture.Client"))
17 | .AddJsonFile("appsettings.json")
18 | .AddJsonFile($"appsettings.{currentEnvironment}.json")
19 | .Build();
20 |
21 | var optionsBuilder = new DbContextOptionsBuilder();
22 | optionsBuilder.UseSqlite(
23 | configuration.GetConnectionString("DefaultConnection"),
24 | b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));
25 | return new ApplicationDbContext(optionsBuilder.Options);
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Infrastructure/DesktopClearArchitecture.Infrastructure.Persistence/Repositories/Repository.cs:
--------------------------------------------------------------------------------
1 | #nullable enable
2 |
3 | namespace DesktopClearArchitecture.Infrastructure.Persistence.Repositories;
4 |
5 | using System.Linq.Expressions;
6 | using System.Reflection;
7 | using DesktopClearArchitecture.Domain.Abstractions.Repositories;
8 | using Extensions;
9 | using Microsoft.EntityFrameworkCore;
10 | using Microsoft.EntityFrameworkCore.ChangeTracking;
11 | using Microsoft.EntityFrameworkCore.Metadata;
12 | using Microsoft.EntityFrameworkCore.Query;
13 |
14 | ///
15 | /// Represents a default generic repository implements the interface.
16 | ///
17 | /// The type of the entity.
18 | public sealed class Repository : IRepository
19 | where TEntity : class
20 | {
21 | private readonly DbContext _dbContext;
22 | private readonly DbSet _dbSet;
23 |
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | /// The database context.
28 | public Repository(DbContext dbContext)
29 | {
30 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
31 | _dbSet = _dbContext.Set();
32 | }
33 |
34 | ///
35 | public void ChangeEntityState(TEntity entity, EntityState state)
36 | {
37 | _dbContext.Entry(entity).State = state;
38 | }
39 |
40 | ///
41 | public void ChangeTable(string table)
42 | {
43 | if (_dbContext.Model.FindEntityType(typeof(TEntity)) is IConventionEntityType relational)
44 | relational.SetTableName(table);
45 | }
46 |
47 | ///
48 | public IQueryable GetAll(bool disableTracking = true)
49 | {
50 | return disableTracking
51 | ? _dbSet.AsNoTracking()
52 | : _dbSet;
53 | }
54 |
55 | ///
56 | public IQueryable GetAll(
57 | Expression> selector,
58 | bool disableTracking = true)
59 | {
60 | return disableTracking
61 | ? _dbSet.AsNoTracking().Select(selector)
62 | : _dbSet.Select(selector);
63 | }
64 |
65 | ///
66 | public IQueryable GetAll(
67 | Expression> selector,
68 | Expression>? predicate = null,
69 | bool disableTracking = true)
70 | {
71 | IQueryable query = _dbSet;
72 |
73 | if (disableTracking)
74 | query = query.AsNoTracking();
75 |
76 | if (predicate is not null)
77 | query = query.Where(predicate);
78 |
79 | return query.Select(selector);
80 | }
81 |
82 | ///
83 | public IQueryable GetAll(
84 | Expression>? predicate = null,
85 | Func, IOrderedQueryable>? orderBy = null,
86 | Func, IIncludableQueryable>? include = null,
87 | bool disableTracking = true,
88 | bool ignoreQueryFilters = false)
89 | {
90 | IQueryable query = _dbSet;
91 |
92 | if (disableTracking)
93 | query = query.AsNoTracking();
94 |
95 | if (include is not null)
96 | query = include(query);
97 |
98 | if (predicate is not null)
99 | query = query.Where(predicate);
100 |
101 | if (ignoreQueryFilters)
102 | query = query.IgnoreQueryFilters();
103 |
104 | return orderBy is not null
105 | ? orderBy(query)
106 | : query;
107 | }
108 |
109 | ///
110 | public IQueryable GetAll(
111 | Expression> selector,
112 | Expression>? predicate = null,
113 | Func, IOrderedQueryable>? orderBy = null,
114 | Func, IIncludableQueryable>? include = null,
115 | bool disableTracking = true,
116 | bool ignoreQueryFilters = false)
117 | {
118 | IQueryable query = _dbSet;
119 |
120 | if (disableTracking)
121 | query = query.AsNoTracking();
122 |
123 | if (include is not null)
124 | query = include(query);
125 |
126 | if (predicate is not null)
127 | query = query.Where(predicate);
128 |
129 | if (ignoreQueryFilters)
130 | query = query.IgnoreQueryFilters();
131 |
132 | return orderBy != null
133 | ? orderBy(query).Select(selector)
134 | : query.Select(selector);
135 | }
136 |
137 | ///
138 | public async Task> GetAllAsync(bool disableTracking = true)
139 | {
140 | return disableTracking
141 | ? await _dbSet.AsNoTracking().ToListAsync()
142 | : await _dbSet.ToListAsync();
143 | }
144 |
145 | ///
146 | public async Task> GetAllAsync(
147 | Expression> selector,
148 | bool disableTracking = true)
149 | {
150 | return disableTracking
151 | ? await _dbSet.AsNoTracking().Select(selector).ToListAsync()
152 | : await _dbSet.Select(selector).ToListAsync();
153 | }
154 |
155 | ///
156 | public async Task> GetAllAsync(
157 | Expression>? predicate = null,
158 | Func, IOrderedQueryable>? orderBy = null,
159 | Func, IIncludableQueryable>? include = null,
160 | bool disableTracking = true,
161 | bool ignoreQueryFilters = false)
162 | {
163 | IQueryable query = _dbSet;
164 |
165 | if (disableTracking)
166 | query = query.AsNoTracking();
167 |
168 | if (include is not null)
169 | query = include(query);
170 |
171 | if (predicate is not null)
172 | query = query.Where(predicate);
173 |
174 | if (ignoreQueryFilters)
175 | query = query.IgnoreQueryFilters();
176 |
177 | if (orderBy is not null)
178 | return await orderBy(query).ToListAsync();
179 |
180 | return await query.ToListAsync();
181 | }
182 |
183 | ///
184 | public async Task> GetAllAsync(
185 | Expression> selector,
186 | Expression>? predicate = null,
187 | Func, IOrderedQueryable>? orderBy = null,
188 | Func, IIncludableQueryable>? include = null,
189 | bool disableTracking = true,
190 | bool ignoreQueryFilters = false)
191 | {
192 | IQueryable query = _dbSet;
193 |
194 | if (disableTracking)
195 | query = query.AsNoTracking();
196 |
197 | if (include is not null)
198 | query = include(query);
199 |
200 | if (predicate is not null)
201 | query = query.Where(predicate);
202 |
203 | if (ignoreQueryFilters)
204 | query = query.IgnoreQueryFilters();
205 |
206 | return orderBy is not null
207 | ? await orderBy(query).Select(selector).ToListAsync()
208 | : await query.Select(selector).ToListAsync();
209 | }
210 |
211 | ///
212 | public IPagedList GetPagedList(
213 | Expression>? predicate = null,
214 | Func, IOrderedQueryable>? orderBy = null,
215 | Func, IIncludableQueryable>? include = null,
216 | int pageIndex = 0,
217 | int pageSize = 20,
218 | bool disableTracking = true,
219 | bool ignoreQueryFilters = false)
220 | {
221 | IQueryable query = _dbSet;
222 |
223 | if (disableTracking)
224 | query = query.AsNoTracking();
225 |
226 | if (include is not null)
227 | query = include(query);
228 |
229 | if (predicate is not null)
230 | query = query.Where(predicate);
231 |
232 | if (ignoreQueryFilters)
233 | query = query.IgnoreQueryFilters();
234 |
235 | return orderBy is not null
236 | ? orderBy(query).ToPagedList(pageIndex, pageSize)
237 | : query.ToPagedList(pageIndex, pageSize);
238 | }
239 |
240 | ///
241 | public Task> GetPagedListAsync(
242 | Expression>? predicate = null,
243 | Func, IOrderedQueryable>? orderBy = null,
244 | Func, IIncludableQueryable>? include = null,
245 | int pageIndex = 0,
246 | int pageSize = 20,
247 | bool disableTracking = true,
248 | CancellationToken cancellationToken = default,
249 | bool ignoreQueryFilters = false)
250 | {
251 | IQueryable query = _dbSet;
252 |
253 | if (disableTracking)
254 | query = query.AsNoTracking();
255 |
256 | if (include is not null)
257 | query = include(query);
258 |
259 | if (predicate is not null)
260 | query = query.Where(predicate);
261 |
262 | if (ignoreQueryFilters)
263 | query = query.IgnoreQueryFilters();
264 |
265 | return orderBy is not null
266 | ? orderBy(query).ToPagedListAsync(pageIndex, pageSize, 0, cancellationToken)
267 | : query.ToPagedListAsync(pageIndex, pageSize, 0, cancellationToken);
268 | }
269 |
270 | ///
271 | public IPagedList GetPagedList(
272 | Expression> selector,
273 | Expression>? predicate = null,
274 | Func, IOrderedQueryable>? orderBy = null,
275 | Func, IIncludableQueryable>? include = null,
276 | int pageIndex = 0,
277 | int pageSize = 20,
278 | bool disableTracking = true,
279 | bool ignoreQueryFilters = false)
280 | where TResult : class
281 | {
282 | IQueryable query = _dbSet;
283 |
284 | if (disableTracking)
285 | query = query.AsNoTracking();
286 |
287 | if (include is not null)
288 | query = include(query);
289 |
290 | if (predicate is not null)
291 | query = query.Where(predicate);
292 |
293 | if (ignoreQueryFilters)
294 | query = query.IgnoreQueryFilters();
295 |
296 | return orderBy is not null
297 | ? orderBy(query).Select(selector).ToPagedList(pageIndex, pageSize)
298 | : query.Select(selector).ToPagedList(pageIndex, pageSize);
299 | }
300 |
301 | ///
302 | public Task> GetPagedListAsync(
303 | Expression> selector,
304 | Expression>? predicate = null,
305 | Func, IOrderedQueryable>? orderBy = null,
306 | Func, IIncludableQueryable>? include = null,
307 | int pageIndex = 0,
308 | int pageSize = 20,
309 | bool disableTracking = true,
310 | CancellationToken cancellationToken = default,
311 | bool ignoreQueryFilters = false)
312 | where TResult : class
313 | {
314 | if (selector == null)
315 | throw new ArgumentNullException(nameof(selector));
316 |
317 | IQueryable query = _dbSet;
318 |
319 | if (disableTracking)
320 | query = query.AsNoTracking();
321 |
322 | if (include != null)
323 | query = include(query);
324 |
325 | if (predicate != null)
326 | query = query.Where(predicate);
327 |
328 | if (ignoreQueryFilters)
329 | query = query.IgnoreQueryFilters();
330 |
331 | if (orderBy != null)
332 | return orderBy(query).Select(selector).ToPagedListAsync(pageIndex, pageSize, 0, cancellationToken);
333 |
334 | return query.Select(selector).ToPagedListAsync(pageIndex, pageSize, 0, cancellationToken);
335 | }
336 |
337 | ///
338 | public TEntity? GetFirstOrDefault(
339 | Expression>? predicate = null,
340 | Func, IOrderedQueryable>? orderBy = null,
341 | Func, IIncludableQueryable>? include = null,
342 | bool disableTracking = true,
343 | bool ignoreQueryFilters = false)
344 | {
345 | IQueryable query = _dbSet;
346 |
347 | if (disableTracking)
348 | query = query.AsNoTracking();
349 |
350 | if (include is not null)
351 | query = include(query);
352 |
353 | if (predicate is not null)
354 | query = query.Where(predicate);
355 |
356 | if (ignoreQueryFilters)
357 | query = query.IgnoreQueryFilters();
358 |
359 | return orderBy is not null
360 | ? orderBy(query).FirstOrDefault()
361 | : query.FirstOrDefault();
362 | }
363 |
364 | ///
365 | public async Task GetFirstOrDefaultAsync(
366 | Expression>? predicate = null,
367 | Func, IOrderedQueryable>? orderBy = null,
368 | Func, IIncludableQueryable>? include = null,
369 | bool disableTracking = true,
370 | bool ignoreQueryFilters = false)
371 | {
372 | IQueryable query = _dbSet;
373 |
374 | if (disableTracking)
375 | query = query.AsNoTracking();
376 |
377 | if (include is not null)
378 | query = include(query);
379 |
380 | if (predicate is not null)
381 | query = query.Where(predicate);
382 |
383 | if (ignoreQueryFilters)
384 | query = query.IgnoreQueryFilters();
385 |
386 | return orderBy is not null
387 | ? await orderBy(query).FirstOrDefaultAsync()
388 | : await query.FirstOrDefaultAsync();
389 | }
390 |
391 | ///
392 | public TResult? GetFirstOrDefault(
393 | Expression> selector,
394 | Expression>? predicate = null,
395 | Func, IOrderedQueryable>? orderBy = null,
396 | Func, IIncludableQueryable>? include = null,
397 | bool disableTracking = true,
398 | bool ignoreQueryFilters = false)
399 | {
400 | IQueryable query = _dbSet;
401 |
402 | if (disableTracking)
403 | query = query.AsNoTracking();
404 |
405 | if (include is not null)
406 | query = include(query);
407 |
408 | if (predicate is not null)
409 | query = query.Where(predicate);
410 |
411 | if (ignoreQueryFilters)
412 | query = query.IgnoreQueryFilters();
413 |
414 | return orderBy is not null
415 | ? orderBy(query).Select(selector).FirstOrDefault()
416 | : query.Select(selector).FirstOrDefault();
417 | }
418 |
419 | ///
420 | public async Task GetFirstOrDefaultAsync(
421 | Expression> selector,
422 | Expression>? predicate = null,
423 | Func, IOrderedQueryable>? orderBy = null,
424 | Func, IIncludableQueryable>? include = null,
425 | bool disableTracking = true,
426 | bool ignoreQueryFilters = false)
427 | {
428 | IQueryable query = _dbSet;
429 |
430 | if (disableTracking)
431 | query = query.AsNoTracking();
432 |
433 | if (include is not null)
434 | query = include(query);
435 |
436 | if (predicate is not null)
437 | query = query.Where(predicate);
438 |
439 | if (ignoreQueryFilters)
440 | query = query.IgnoreQueryFilters();
441 |
442 | return orderBy is not null
443 | ? await orderBy(query).Select(selector).FirstOrDefaultAsync()
444 | : await query.Select(selector).FirstOrDefaultAsync();
445 | }
446 |
447 | ///
448 | public IQueryable FromSql(string sql, params object[] parameters)
449 | {
450 | return _dbSet.FromSqlRaw(sql, parameters);
451 | }
452 |
453 | ///
454 | public TEntity? Find(params object[] keyValues)
455 | {
456 | return _dbSet.Find(keyValues);
457 | }
458 |
459 | ///
460 | public ValueTask FindAsync(params object[] keyValues)
461 | {
462 | return _dbSet.FindAsync(keyValues)!;
463 | }
464 |
465 | ///
466 | public ValueTask FindAsync(object[] keyValues, CancellationToken cancellationToken)
467 | {
468 | return _dbSet.FindAsync(keyValues, cancellationToken)!;
469 | }
470 |
471 | ///
472 | public int Count(Expression>? predicate = null)
473 | {
474 | return predicate is null
475 | ? _dbSet.Count()
476 | : _dbSet.Count(predicate);
477 | }
478 |
479 | ///
480 | public async Task CountAsync(
481 | Expression>? predicate = null,
482 | CancellationToken cancellationToken = default)
483 | {
484 | return predicate is null
485 | ? await _dbSet.CountAsync(cancellationToken)
486 | : await _dbSet.CountAsync(predicate, cancellationToken);
487 | }
488 |
489 | ///
490 | public long LongCount(Expression>? predicate = null)
491 | {
492 | return predicate is null
493 | ? _dbSet.LongCount()
494 | : _dbSet.LongCount(predicate);
495 | }
496 |
497 | ///
498 | public async Task LongCountAsync(
499 | Expression>? predicate = null,
500 | CancellationToken cancellationToken = default)
501 | {
502 | return predicate is null
503 | ? await _dbSet.LongCountAsync(cancellationToken)
504 | : await _dbSet.LongCountAsync(predicate, cancellationToken);
505 | }
506 |
507 | ///
508 | public bool Exists(Expression>? predicate = null)
509 | {
510 | return predicate is null
511 | ? _dbSet.Any()
512 | : _dbSet.Any(predicate);
513 | }
514 |
515 | ///
516 | public async Task ExistsAsync(
517 | Expression>? selector = null,
518 | CancellationToken cancellationToken = default)
519 | {
520 | return selector is null
521 | ? await _dbSet.AnyAsync(cancellationToken)
522 | : await _dbSet.AnyAsync(selector, cancellationToken);
523 | }
524 |
525 | ///
526 | public T? Max(
527 | Expression> selector,
528 | Expression>? predicate = null)
529 | {
530 | return predicate is null
531 | ? _dbSet.Max(selector)
532 | : _dbSet.Where(predicate).Max(selector);
533 | }
534 |
535 | ///
536 | public Task MaxAsync(
537 | Expression> selector,
538 | Expression>? predicate = null,
539 | CancellationToken cancellationToken = default)
540 | {
541 | return predicate is null
542 | ? _dbSet.MaxAsync(selector, cancellationToken)
543 | : _dbSet.Where(predicate).MaxAsync(selector, cancellationToken);
544 | }
545 |
546 | ///
547 | public T? Min(
548 | Expression> selector,
549 | Expression>? predicate = null)
550 | {
551 | return predicate is null
552 | ? _dbSet.Min(selector)
553 | : _dbSet.Where(predicate).Min(selector);
554 | }
555 |
556 | ///
557 | public Task MinAsync(
558 | Expression> selector,
559 | Expression>? predicate = null,
560 | CancellationToken cancellationToken = default)
561 | {
562 | return predicate is null
563 | ? _dbSet.MinAsync(selector, cancellationToken)
564 | : _dbSet.Where(predicate).MinAsync(selector, cancellationToken);
565 | }
566 |
567 | ///
568 | public decimal Average(
569 | Expression> selector,
570 | Expression>? predicate = null)
571 | {
572 | return predicate is null
573 | ? _dbSet.Average(selector)
574 | : _dbSet.Where(predicate).Average(selector);
575 | }
576 |
577 | ///
578 | public Task AverageAsync(
579 | Expression> selector,
580 | Expression>? predicate = null,
581 | CancellationToken cancellationToken = default)
582 | {
583 | return predicate is null
584 | ? _dbSet.AverageAsync(selector, cancellationToken)
585 | : _dbSet.Where(predicate).AverageAsync(selector, cancellationToken);
586 | }
587 |
588 | ///
589 | public decimal Sum(
590 | Expression> selector,
591 | Expression>? predicate = null)
592 | {
593 | return predicate is null
594 | ? _dbSet.Sum(selector)
595 | : _dbSet.Where(predicate).Sum(selector);
596 | }
597 |
598 | ///
599 | public Task SumAsync(
600 | Expression> selector,
601 | Expression>? predicate = null,
602 | CancellationToken cancellationToken = default)
603 | {
604 | return predicate is null
605 | ? _dbSet.SumAsync(selector, cancellationToken)
606 | : _dbSet.Where(predicate).SumAsync(selector, cancellationToken);
607 | }
608 |
609 | ///