实例介绍
干净架构是一种软件设计哲学,它强调以用例为中心的组织结构,确保应用程序的核心逻辑与外部框架和技术细节解耦。本文介绍了一个使用.NET Core和React Redux实现干净架构原则的示例项目,旨在通过小型、独立开发和测试的组件构建应用程序。
我们提供了三个版本的支持:
- .NET 6
- .NET 5
- .NET Core 3.1
该项目还包括一个虚拟钱包解决方案示例,用户可以注册账户并通过存款、提款和转账操作管理余额。
动机
学习如何设计模块化应用程序和探索.NET Core的特性,将帮助您成为更优秀的工程师。设计模块化应用程序是软件架构的圣杯,能够持续稳定地添加新功能是每位工程师追求的目标。
.NET Core提供了一个甜蜜的开发环境,它是一个可扩展且跨平台的框架。我们将探索它在基础设施层的好处,并在应用程序和域层减少其重要性。现代C#语言语法也遵循同样的规则。
【实例截图】
【核心代码】
文件清单
└── clean-architecture-manga-23e3d00555e2f94f7399a21a27a193decace353b
├── CHANGELOG.md
├── Clean-Architecture-Manga.sln
├── Clean-Architecture-Manga.sln.DotSettings
├── FUNDING.yml
├── LICENSE
├── README.md
├── accounts-api
│ ├── Directory.Build.props
│ ├── nuget.config
│ ├── src
│ │ ├── Application
│ │ │ ├── Application.csproj
│ │ │ ├── Messages.Designer.cs
│ │ │ ├── Messages.resx
│ │ │ ├── Services
│ │ │ │ ├── ICurrencyExchange.cs
│ │ │ │ ├── IUnitOfWork.cs
│ │ │ │ ├── IUserService.cs
│ │ │ │ └── Notification.cs
│ │ │ └── UseCases
│ │ │ ├── CloseAccount
│ │ │ │ ├── CloseAccountPresenter.cs
│ │ │ │ ├── CloseAccountUseCase.cs
│ │ │ │ ├── CloseAccountValidationUseCase.cs
│ │ │ │ ├── ICloseAccountUseCase.cs
│ │ │ │ └── IOutputPort.cs
│ │ │ ├── Deposit
│ │ │ │ ├── DepositPresenter.cs
│ │ │ │ ├── DepositUseCase.cs
│ │ │ │ ├── DepositValidationUseCase.cs
│ │ │ │ ├── IDepositUseCase.cs
│ │ │ │ └── IOutputPort.cs
│ │ │ ├── GetAccount
│ │ │ │ ├── GetAccountPresenter.cs
│ │ │ │ ├── GetAccountUseCase.cs
│ │ │ │ ├── GetAccountValidationUseCase.cs
│ │ │ │ ├── IGetAccountUseCase.cs
│ │ │ │ └── IOutputPort.cs
│ │ │ ├── GetAccounts
│ │ │ │ ├── GetAccountPresenter.cs
│ │ │ │ ├── GetAccountsUseCase.cs
│ │ │ │ ├── IGetAccountsUseCase.cs
│ │ │ │ └── IOutputPort.cs
│ │ │ ├── OpenAccount
│ │ │ │ ├── IOpenAccountUseCase.cs
│ │ │ │ ├── IOutputPort.cs
│ │ │ │ ├── OpenAccountPresenter.cs
│ │ │ │ ├── OpenAccountUseCase.cs
│ │ │ │ └── OpenAccountValidationUseCase.cs
│ │ │ ├── Transfer
│ │ │ │ ├── IOutputPort.cs
│ │ │ │ ├── ITransferUseCase.cs
│ │ │ │ ├── TransferPresenter.cs
│ │ │ │ ├── TransferUseCase.cs
│ │ │ │ └── TransferValidationUseCase.cs
│ │ │ └── Withdraw
│ │ │ ├── IOutputPort.cs
│ │ │ ├── IWithdrawUseCase.cs
│ │ │ ├── WithdrawPresenter.cs
│ │ │ ├── WithdrawUseCase.cs
│ │ │ └── WithdrawValidationUseCase.cs
│ │ ├── Domain
│ │ │ ├── Account.cs
│ │ │ ├── AccountNull.cs
│ │ │ ├── Credits
│ │ │ │ ├── Credit.cs
│ │ │ │ ├── CreditNull.cs
│ │ │ │ ├── CreditsCollection.cs
│ │ │ │ └── ICredit.cs
│ │ │ ├── Debits
│ │ │ │ ├── Debit.cs
│ │ │ │ ├── DebitNull.cs
│ │ │ │ ├── DebitsCollection.cs
│ │ │ │ └── IDebit.cs
│ │ │ ├── Domain.csproj
│ │ │ ├── IAccount.cs
│ │ │ ├── IAccountFactory.cs
│ │ │ ├── IAccountRepository.cs
│ │ │ ├── Messages.Designer.cs
│ │ │ ├── Messages.resx
│ │ │ └── ValueObjects
│ │ │ ├── AccountId.cs
│ │ │ ├── CreditId.cs
│ │ │ ├── Currency.cs
│ │ │ ├── DebitId.cs
│ │ │ └── Money.cs
│ │ ├── Infrastructure
│ │ │ ├── CurrencyExchange
│ │ │ │ ├── CurrencyExchangeFake.cs
│ │ │ │ └── CurrencyExchangeService.cs
│ │ │ ├── DataAccess
│ │ │ │ ├── Configuration
│ │ │ │ │ ├── AccountConfiguration.cs
│ │ │ │ │ ├── CreditConfiguration.cs
│ │ │ │ │ └── DebitConfiguration.cs
│ │ │ │ ├── ContextFactory.cs
│ │ │ │ ├── EntityFactory.cs
│ │ │ │ ├── MangaContext.cs
│ │ │ │ ├── MangaContextFake.cs
│ │ │ │ ├── Migrations
│ │ │ │ │ ├── InitialCreate.Designer.cs
│ │ │ │ │ ├── InitialCreate.cs
│ │ │ │ │ └── MangaContextModelSnapshot.cs
│ │ │ │ ├── Repositories
│ │ │ │ │ ├── AccountRepository.cs
│ │ │ │ │ └── AccountRepositoryFake.cs
│ │ │ │ ├── SeedData.cs
│ │ │ │ ├── UnitOfWork.cs
│ │ │ │ └── UnitOfWorkFake.cs
│ │ │ ├── ExternalAuthentication
│ │ │ │ ├── ExternalUserService.cs
│ │ │ │ └── TestUserService.cs
│ │ │ ├── Infrastructure.csproj
│ │ │ ├── Messages.Designer.cs
│ │ │ └── Messages.resx
│ │ └── WebApi
│ │ ├── Dockerfile
│ │ ├── Modules
│ │ │ ├── Common
│ │ │ │ ├── AuthenticationExtensions.cs
│ │ │ │ ├── CustomApiConventions.cs
│ │ │ │ ├── CustomControllersExtensions.cs
│ │ │ │ ├── CustomCorsExtensions.cs
│ │ │ │ ├── DataProtectionExtensions.cs
│ │ │ │ ├── ExceptionFilter.cs
│ │ │ │ ├── FeatureFlags
│ │ │ │ │ ├── CustomControllerFeatureProvider.cs
│ │ │ │ │ ├── CustomFeature.cs
│ │ │ │ │ └── FeatureFlagsExtensions.cs
│ │ │ │ ├── HttpMetricsExtensions.cs
│ │ │ │ ├── LoggingExtensions.cs
│ │ │ │ ├── ReverseProxyExtensions.cs
│ │ │ │ ├── Swagger
│ │ │ │ │ ├── ConfigureSwaggerOptions.cs
│ │ │ │ │ └── SwaggerExtensions.cs
│ │ │ │ ├── TestAuthenticationHandler.cs
│ │ │ │ └── VersioningExtensions.cs
│ │ │ ├── CurrencyExchangeExtensions.cs
│ │ │ ├── HealthChecksExtensions.cs
│ │ │ ├── SQLServerExtensions.cs
│ │ │ └── UseCasesExtensions.cs
│ │ ├── Program.cs
│ │ ├── Startup.cs
│ │ ├── UseCases
│ │ │ ├── V1
│ │ │ │ ├── Accounts
│ │ │ │ │ ├── CloseAccount
│ │ │ │ │ │ ├── AccountsController.cs
│ │ │ │ │ │ └── CloseAccountResponse.cs
│ │ │ │ │ ├── GetAccount
│ │ │ │ │ │ ├── AccountsController.cs
│ │ │ │ │ │ └── GetAccountResponse.cs
│ │ │ │ │ ├── GetAccounts
│ │ │ │ │ │ ├── AccountsController.cs
│ │ │ │ │ │ └── GetAccountsResponse.cs
│ │ │ │ │ └── OpenAccount
│ │ │ │ │ ├── AccountsController.cs
│ │ │ │ │ └── OpenAccountResponse.cs
│ │ │ │ ├── CustomError
│ │ │ │ │ ├── CustomError.cshtml
│ │ │ │ │ ├── CustomErrorController.cs
│ │ │ │ │ ├── CustomErrorResponse.cs
│ │ │ │ │ └── _ViewImports.cshtml
│ │ │ │ └── Transactions
│ │ │ │ ├── Deposit
│ │ │ │ │ ├── DepositResponse.cs
│ │ │ │ │ └── TransactionsController.cs
│ │ │ │ ├── Transfer
│ │ │ │ │ ├── TransactionsController.cs
│ │ │ │ │ └── TransferResponse.cs
│ │ │ │ └── Withdraw
│ │ │ │ ├── TransactionsController.cs
│ │ │ │ └── WithdrawResponse.cs
│ │ │ └── V2
│ │ │ └── Accounts
│ │ │ └── GetAccount
│ │ │ ├── AccountsController.cs
│ │ │ └── GetAccountDetailsRequestV2.cs
│ │ ├── ViewModels
│ │ │ ├── AccountDetailsModel.cs
│ │ │ ├── AccountModel.cs
│ │ │ ├── CreditModel.cs
│ │ │ └── DebitModel.cs
│ │ ├── WebApi.csproj
│ │ ├── appsettings.Development.json
│ │ ├── appsettings.Production.json
│ │ ├── appsettings.json
│ │ ├── entrypoint.sh
│ │ ├── key-735c3c44-2bf6-4a13-8fbc-fa34519cefc8.xml
│ │ └── key-af978992-f745-47fa-b0ac-106eb5d9faee.xml
│ └── test
│ ├── ComponentTests
│ │ ├── ComponentTests.csproj
│ │ ├── CustomWebApplicationFactory.cs
│ │ ├── CustomWebApplicationFactoryCollection.cs
│ │ ├── CustomWebApplicationFactoryFixture.cs
│ │ ├── TestAuthenticationHandler.cs
│ │ ├── V1
│ │ │ ├── GetAccountsTests.cs
│ │ │ └── SunnyDayTests.cs
│ │ └── V2
│ │ └── SunnyDayTests.cs
│ ├── EndToEndTests
│ │ ├── CustomWebApplicationFactory.cs
│ │ ├── CustomWebApplicationFactoryCollection.cs
│ │ ├── CustomWebApplicationFactoryFixture.cs
│ │ ├── EndToEndTests.csproj
│ │ ├── TestAuthenticationHandler.cs
│ │ └── V1
│ │ └── GetAccountsTests.cs
│ ├── IntegrationTests
│ │ ├── CurrencyExchangeTests
│ │ │ └── ConvertEuroToDollarTests.cs
│ │ ├── EntityFrameworkTests
│ │ │ ├── AccountRepositoryTests.cs
│ │ │ └── StandardFixture.cs
│ │ └── IntegrationTests.csproj
│ └── UnitTests
│ ├── CloseAccount
│ │ ├── CloseAccountTests.cs
│ │ └── ValidDataSetup.cs
│ ├── Deposit
│ │ ├── DepositTests.cs
│ │ ├── InvalidDataSetup.cs
│ │ └── ValidDataSetup.cs
│ ├── OpenAccount
│ │ ├── OpenAccountTests.cs
│ │ └── ValidDataSetup.cs
│ ├── StandardFixture.cs
│ ├── Transfer
│ │ ├── TransferUseCaseTests.cs
│ │ └── ValidDataSetup.cs
│ ├── UnitTests.csproj
│ └── Withdraw
│ ├── ValidDataSetup.cs
│ └── WithdrawTests.cs
├── accounts-api-seed
│ └── Dockerfile
├── docker-compose
│ ├── docker-compose.backend-only.yml
│ ├── docker-compose.dcproj
│ ├── docker-compose.override.yml
│ ├── docker-compose.production.yml
│ ├── docker-compose.yml
│ ├── setup.production.sh
│ ├── setup.ps1
│ ├── setup.sh
│ └── ssl-selfsigned.cnf
├── identity-server
│ ├── Config.cs
│ ├── Dockerfile
│ ├── IdentityServer.csproj
│ ├── Modules
│ │ └── Common
│ │ ├── CustomCorsExtensions.cs
│ │ ├── DataProtectionExtensions.cs
│ │ └── ReverseProxyExtensions.cs
│ ├── Program.cs
│ ├── Quickstart
│ │ ├── Account
│ │ │ ├── AccountController.cs
│ │ │ ├── AccountOptions.cs
│ │ │ ├── ExternalController.cs
│ │ │ ├── ExternalProvider.cs
│ │ │ ├── LoggedOutViewModel.cs
│ │ │ ├── LoginInputModel.cs
│ │ │ ├── LoginViewModel.cs
│ │ │ ├── LogoutInputModel.cs
│ │ │ ├── LogoutViewModel.cs
│ │ │ └── RedirectViewModel.cs
│ │ ├── Consent
│ │ │ ├── ConsentController.cs
│ │ │ ├── ConsentInputModel.cs
│ │ │ ├── ConsentOptions.cs
│ │ │ ├── ConsentViewModel.cs
│ │ │ ├── ProcessConsentResult.cs
│ │ │ └── ScopeViewModel.cs
│ │ ├── Device
│ │ │ ├── DeviceAuthorizationInputModel.cs
│ │ │ ├── DeviceAuthorizationViewModel.cs
│ │ │ └── DeviceController.cs
│ │ ├── Diagnostics
│ │ │ ├── DiagnosticsController.cs
│ │ │ └── DiagnosticsViewModel.cs
│ │ ├── Extensions.cs
│ │ ├── Grants
│ │ │ ├── GrantViewModel.cs
│ │ │ ├── GrantsController.cs
│ │ │ └── GrantsViewModel.cs
│ │ ├── Home
│ │ │ ├── ErrorViewModel.cs
│ │ │ └── HomeController.cs
│ │ ├── SecurityHeadersAttribute.cs
│ │ └── TestUsers.cs
│ ├── Startup.cs
│ ├── Views
│ │ ├── Account
│ │ │ ├── AccessDenied.cshtml
│ │ │ ├── LoggedOut.cshtml
│ │ │ ├── Login.cshtml
│ │ │ └── Logout.cshtml
│ │ ├── Consent
│ │ │ └── Index.cshtml
│ │ ├── Device
│ │ │ ├── Success.cshtml
│ │ │ ├── UserCodeCapture.cshtml
│ │ │ └── UserCodeConfirmation.cshtml
│ │ ├── Diagnostics
│ │ │ └── Index.cshtml
│ │ ├── Grants
│ │ │ └── Index.cshtml
│ │ ├── Home
│ │ │ └── Index.cshtml
│ │ ├── Shared
│ │ │ ├── Error.cshtml
│ │ │ ├── Redirect.cshtml
│ │ │ ├── _Layout.cshtml
│ │ │ ├── _Nav.cshtml
│ │ │ ├── _ScopeListItem.cshtml
│ │ │ └── _ValidationSummary.cshtml
│ │ ├── _ViewImports.cshtml
│ │ └── _ViewStart.cshtml
│ ├── appsettings.json
│ ├── key-cdb485fc-6967-4f51-af4c-5d1467e4d4c4.xml
│ ├── key-f0378622-9325-4684-8be6-856988198ac4.xml
│ ├── tempkey.jwk
│ ├── updateUI.ps1
│ └── wwwroot
│ ├── css
│ │ ├── site.css
│ │ ├── site.min.css
│ │ └── site.scss
│ ├── favicon.ico
│ ├── icon.jpg
│ ├── icon.png
│ ├── js
│ │ ├── signin-redirect.js
│ │ └── signout-redirect.js
│ └── lib
│ ├── bootstrap
│ │ ├── README.md
│ │ ├── dist
│ │ │ ├── css
│ │ │ │ ├── bootstrap-grid.css
│ │ │ │ ├── bootstrap-grid.css.map
│ │ │ │ ├── bootstrap-grid.min.css
│ │ │ │ ├── bootstrap-grid.min.css.map
│ │ │ │ ├── bootstrap-reboot.css
│ │ │ │ ├── bootstrap-reboot.css.map
│ │ │ │ ├── bootstrap-reboot.min.css
│ │ │ │ ├── bootstrap-reboot.min.css.map
│ │ │ │ ├── bootstrap.css
│ │ │ │ ├── bootstrap.css.map
│ │ │ │ ├── bootstrap.min.css
│ │ │ │ └── bootstrap.min.css.map
│ │ │ └── js
│ │ │ ├── bootstrap.bundle.js
│ │ │ ├── bootstrap.bundle.js.map
│ │ │ ├── bootstrap.bundle.min.js
│ │ │ ├── bootstrap.bundle.min.js.map
│ │ │ ├── bootstrap.js
│ │ │ ├── bootstrap.js.map
│ │ │ ├── bootstrap.min.js
│ │ │ └── bootstrap.min.js.map
│ │ └── scss
│ │ ├── _alert.scss
│ │ ├── _badge.scss
│ │ ├── _breadcrumb.scss
│ │ ├── _button-group.scss
│ │ ├── _buttons.scss
│ │ ├── _card.scss
│ │ ├── _carousel.scss
│ │ ├── _close.scss
│ │ ├── _code.scss
│ │ ├── _custom-forms.scss
│ │ ├── _dropdown.scss
│ │ ├── _forms.scss
│ │ ├── _functions.scss
│ │ ├── _grid.scss
│ │ ├── _images.scss
│ │ ├── _input-group.scss
│ │ ├── _jumbotron.scss
│ │ ├── _list-group.scss
│ │ ├── _media.scss
│ │ ├── _mixins.scss
│ │ ├── _modal.scss
│ │ ├── _nav.scss
│ │ ├── _navbar.scss
│ │ ├── _pagination.scss
│ │ ├── _popover.scss
│ │ ├── _print.scss
│ │ ├── _progress.scss
│ │ ├── _reboot.scss
│ │ ├── _root.scss
│ │ ├── _spinners.scss
│ │ ├── _tables.scss
│ │ ├── _toasts.scss
│ │ ├── _tooltip.scss
│ │ ├── _transitions.scss
│ │ ├── _type.scss
│ │ ├── _utilities.scss
│ │ ├── _variables.scss
│ │ ├── bootstrap-grid.scss
│ │ ├── bootstrap-reboot.scss
│ │ ├── bootstrap.scss
│ │ ├── mixins
│ │ │ ├── _alert.scss
│ │ │ ├── _background-variant.scss
│ │ │ ├── _badge.scss
│ │ │ ├── _border-radius.scss
│ │ │ ├── _box-shadow.scss
│ │ │ ├── _breakpoints.scss
│ │ │ ├── _buttons.scss
│ │ │ ├── _caret.scss
│ │ │ ├── _clearfix.scss
│ │ │ ├── _deprecate.scss
│ │ │ ├── _float.scss
│ │ │ ├── _forms.scss
│ │ │ ├── _gradients.scss
│ │ │ ├── _grid-framework.scss
│ │ │ ├── _grid.scss
│ │ │ ├── _hover.scss
│ │ │ ├── _image.scss
│ │ │ ├── _list-group.scss
│ │ │ ├── _lists.scss
│ │ │ ├── _nav-divider.scss
│ │ │ ├── _pagination.scss
│ │ │ ├── _reset-text.scss
│ │ │ ├── _resize.scss
│ │ │ ├── _screen-reader.scss
│ │ │ ├── _size.scss
│ │ │ ├── _table-row.scss
│ │ │ ├── _text-emphasis.scss
│ │ │ ├── _text-hide.scss
│ │ │ ├── _text-truncate.scss
│ │ │ ├── _transition.scss
│ │ │ └── _visibility.scss
│ │ ├── utilities
│ │ │ ├── _align.scss
│ │ │ ├── _background.scss
│ │ │ ├── _borders.scss
│ │ │ ├── _clearfix.scss
│ │ │ ├── _display.scss
│ │ │ ├── _embed.scss
│ │ │ ├── _flex.scss
│ │ │ ├── _float.scss
│ │ │ ├── _overflow.scss
│ │ │ ├── _position.scss
│ │ │ ├── _screenreaders.scss
│ │ │ ├── _shadows.scss
│ │ │ ├── _sizing.scss
│ │ │ ├── _spacing.scss
│ │ │ ├── _stretched-link.scss
│ │ │ ├── _text.scss
│ │ │ └── _visibility.scss
│ │ └── vendor
│ │ └── _rfs.scss
│ └── jquery
│ ├── LICENSE.txt
│ ├── README.md
│ └── dist
│ ├── jquery.js
│ ├── jquery.min.js
│ ├── jquery.min.map
│ ├── jquery.slim.js
│ ├── jquery.slim.min.js
│ └── jquery.slim.min.map
├── nginx
│ ├── Dockerfile
│ └── nginx.conf
└── wallet-spa
├── Dockerfile
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.jsx
│ ├── components
│ │ ├── Footer.js
│ │ ├── Header.jsx
│ │ ├── Layout.jsx
│ │ ├── MainContent.jsx
│ │ ├── PageBase.js
│ │ ├── SideMenu.jsx
│ │ ├── auth
│ │ │ ├── callback.jsx
│ │ │ ├── logout.jsx
│ │ │ ├── logoutCallback.jsx
│ │ │ ├── register.jsx
│ │ │ └── silentRenew.jsx
│ │ ├── privatePage.jsx
│ │ └── publicPage.jsx
│ ├── custom.css
│ ├── images
│ │ └── material_bg.png
│ ├── index.css
│ ├── index.jsx
│ ├── logo.svg
│ ├── pages
│ │ ├── Account.jsx
│ │ ├── Accounts.jsx
│ │ ├── CloseAccount.jsx
│ │ ├── Deposit.jsx
│ │ ├── OpenAccount.jsx
│ │ ├── Transfer.jsx
│ │ └── Withdraw.jsx
│ ├── providers
│ │ └── authProvider.js
│ ├── routes
│ │ ├── privateRoute.js
│ │ └── routes.js
│ ├── serviceWorker.js
│ ├── store
│ │ ├── accountsService.js
│ │ ├── authService.js
│ │ ├── oauth.js
│ │ └── transactionService.js
│ ├── styles.js
│ ├── styles.scss
│ ├── theme.js
│ └── utils
│ └── authConst.js
└── vs.debug.env
106 directories, 426 files
标签:
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论