Browse Source

Merge branch 'dev' into maliming/async-load

pull/10317/head
maliming 5 years ago
parent
commit
11ceecf538
No known key found for this signature in database GPG Key ID: 96224957E51C89E
  1. 20
      .github/workflows/build-and-test.yml
  2. 2
      .gitignore
  3. 10
      Directory.Build.props
  4. 1
      README.md
  5. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json
  6. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  7. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  8. 4
      build/common.ps1
  9. 2
      build/test-all.ps1
  10. 4
      codecov.yml
  11. 2
      common.props
  12. 11
      docs/en/Background-Jobs-Hangfire.md
  13. 99
      docs/en/Background-Workers-Hangfire.md
  14. 11
      docs/en/Background-Workers.md
  15. 7
      docs/en/Blog-Posts/2021-10-05 v5_0_Beta1/POST.md
  16. 53
      docs/en/Distributed-Event-Bus.md
  17. 50
      docs/en/Local-Event-Bus.md
  18. 3
      docs/en/Module-Entity-Extensions.md
  19. 4
      docs/en/Testing.md
  20. 4
      docs/en/UI/Angular/Config-State-Service.md
  21. 10
      docs/en/UI/Angular/Extensions-Overall.md
  22. 8
      docs/en/docs-nav.json
  23. 100
      docs/zh-Hans/Background-Workers-Hangfire.md
  24. 8
      docs/zh-Hans/Background-Workers.md
  25. 53
      docs/zh-Hans/Distributed-Event-Bus.md
  26. 46
      docs/zh-Hans/Local-Event-Bus.md
  27. 4
      docs/zh-Hans/docs-nav.json
  28. 30
      framework/Volo.Abp.sln
  29. 34
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs
  30. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/AlertsDemo/AlertsDemoViewComponent.cs
  31. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BadgesDemo/BadgesDemoViewComponent.cs
  32. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BordersDemo/BordersDemoViewComponent.cs
  33. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/BreadcrumbsDemoViewComponent.cs
  34. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/ButtonGroupsDemoViewComponent.cs
  35. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonsDemo/ButtonsDemoViewComponent.cs
  36. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CardsDemo/CardsDemoViewComponent.cs
  37. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CarouselDemo/CarouselDemoViewComponent.cs
  38. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CollapseDemo/CollapseDemoViewComponent.cs
  39. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DropdownsDemo/DropdownsDemoViewComponent.cs
  40. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DynamicFormsDemo/DynamicFormsDemoViewComponent.cs
  41. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/FormElementsDemo/FormElementsDemoViewComponent.cs
  42. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/GridsDemo/GridsDemoViewComponent.cs
  43. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ListGroupsDemo/ListGroupsDemoViewComponent.cs
  44. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ModalsDemo/ModalsDemoViewComponent.cs
  45. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavbarsDemo/NavbarsDemoViewComponent.cs
  46. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavsDemo/NavsDemoViewComponent.cs
  47. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/PopoversDemo/PopoversDemoViewComponent.cs
  48. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/ProgressBarsDemoViewComponent.cs
  49. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TablesDemo/TablesDemoViewComponent.cs
  50. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TabsDemo/TabsDemoViewComponent.cs
  51. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TooltipsDemo/TooltipsDemoViewComponent.cs
  52. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpApplicationPath/AbpApplicationPathViewComponent.cs
  53. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpPageSearchBox/AbpPageSearchBoxViewComponent.cs
  54. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpPageToolbar/AbpPageToolbarViewComponent.cs
  55. 41
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar.cs
  56. 36
      framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRConventionalRegistrar.cs
  57. 18
      framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs
  58. 2
      framework/src/Volo.Abp.BackgroundJobs/Volo.Abp.BackgroundJobs.csproj
  59. 4
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobsModule.cs
  60. 103
      framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs
  61. 3
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/FodyWeavers.xml
  62. 2
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/FodyWeavers.xsd
  63. 7
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo.Abp.BackgroundWorkers.Hangfire.csproj
  64. 36
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs
  65. 13
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs
  66. 91
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs
  67. 36
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfirePeriodicBackgroundWorkerAdapter.cs
  68. 15
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/IHangfireBackgroundWorker.cs
  69. 23
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpQuartzConventionalRegistrar.cs
  70. 11
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkerBase.cs
  71. 1
      framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs
  72. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs
  73. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultDotNetProjectBuilder.cs
  74. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
  75. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
  76. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs
  77. 12
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
  78. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  79. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
  80. 22
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs
  81. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs
  82. 109
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs
  83. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs
  84. 23
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
  85. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs
  86. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceConfigureAwaitPropsStep.cs
  87. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs
  88. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmGlobalPackagesChecker.cs
  89. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs
  90. 14
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs
  91. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNpmPackageAdder.cs
  92. 122
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
  93. 7
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
  94. 26
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionPackageVersionFinder.cs
  95. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/Angular/AngularServiceProxyGenerator.cs
  96. 46
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs
  97. 24
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs
  98. 100
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs
  99. 95
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs
  100. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

20
.github/workflows/build-and-test.yml

@ -1,5 +1,22 @@
name: "build and test"
on:
push:
branches:
- dev
paths:
- 'framework/**/*.cs'
- 'framework/**/*.cshtml'
- 'framework/**/*.csproj'
- 'framework/**/*.razor'
- 'modules/**/*.cs'
- 'modules/**/*.cshtml'
- 'modules/**/*.csproj'
- 'modules/**/*.razor'
- 'templates/**/*.cs'
- 'templates/**/*.cshtml'
- 'templates/**/*.csproj'
- 'templates/**/*.razor'
pull_request:
paths:
- 'framework/**/*.cs'
@ -32,3 +49,6 @@ jobs:
run: .\test-all.ps1
working-directory: .\build
shell: powershell
- name: Codecov
uses: codecov/codecov-action@v2

2
.gitignore

@ -314,7 +314,7 @@ abp-build-config.json
tempkey.jwk
# ABP Analyzing files
*.abppkg.analyze.json
# [Disabled for now] *.abppkg.analyze.json
# appsettings.secrets.json
appsettings.secrets.json

10
Directory.Build.props

@ -25,5 +25,15 @@
<!-- Mongo2Go https://www.nuget.org/packages/Mongo2Go -->
<Mongo2GoPackageVersion>3.1.3</Mongo2GoPackageVersion>
<IsTestProject Condition="$(MSBuildProjectFullPath.Contains('test')) and ($(MSBuildProjectName.EndsWith('.Tests')) or $(MSBuildProjectName.EndsWith('.TestBase')))">true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Condition="'$(IsTestProject)' == 'true'" Include="coverlet.collector" Version="3.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

1
README.md

@ -1,6 +1,7 @@
# ABP Framework
![build and test](https://img.shields.io/github/workflow/status/abpframework/abp/build%20and%20test/dev?style=flat-square)
[![codecov](https://codecov.io/gh/abpframework/abp/branch/dev/graph/badge.svg?token=jUKLCxa6HF)](https://codecov.io/gh/abpframework/abp)
[![NuGet](https://img.shields.io/nuget/v/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core)
[![NuGet (with prereleases)](https://img.shields.io/nuget/vpre/Volo.Abp.Core.svg?style=flat-square)](https://www.nuget.org/packages/Volo.Abp.Core)
[![MyGet (nightly builds)](https://img.shields.io/myget/abp-nightly/vpre/Volo.Abp.svg?style=flat-square)](https://docs.abp.io/en/abp/latest/Nightly-Builds)

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json

@ -101,6 +101,7 @@
"WeWillSendYouADownloadLink": "We've sent the file to {0}.",
"InvalidFormInputs": "Please, type the valid information specified on the form.",
"DDDBookEmailBody": "Thank you. <br /> To download your book, <a href=\"{0}\">click here</a>.",
"FreeDDDEBook": "Free DDD E-Book"
"FreeDDDEBook": "Free DDD E-Book",
"CommercialNewsletterConfirmationMessage": "I agree to the <a href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>."
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -388,6 +388,7 @@
"PurchaseTrialLicenseMessage": "Your license expiration date is {0}. <br> If you want to continue using the projects you created during your free trial period, you need to change the license keys in your <code>appsettings.secrets.json</code> files. Here is your license key:",
"TrialLicenseExpireMessage": "You are using the trial license and your trial license will expire on {0}.",
"TryForFree": "Try For Free",
"TrialLicenseExpiredInfo": "Your trial license period has expired!"
"TrialLicenseExpiredInfo": "Your trial license period has expired!",
"CommercialNewsletterConfirmationMessage": "I agree to the <a href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>."
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -98,6 +98,7 @@
"WeWillSendYouADownloadLink": "{0} adresine email gönderilmiştir.",
"InvalidFormInputs": "Lütfen formda belirtilen geçerli bilgileri yazınız.",
"DDDBookEmailBody": "Teşekkürler. <br /> Kitabı indirmek için, <a href=\"{0}\">buraya tıklayınız</a>.",
"FreeDDDEBook": "Ücretsiz DDD E-Kitap"
"FreeDDDEBook": "Ücretsiz DDD E-Kitap",
"CommercialNewsletterConfirmationMessage": "<a href=\"https://commercial.abp.io/TermsConditions\">Şartlar, Koşullar</a> ve <a href=\"https://commercial.abp.io/Privacy\">Gizlilik politikasını</a> kabul ediyorum."
}
}

4
build/common.ps1

@ -7,6 +7,7 @@ $rootFolder = (Get-Item -Path "./" -Verbose).FullName
# List of solutions used only in development mode
$solutionPaths = @(
"../framework",
"../studio",
"../modules/basic-theme",
"../modules/users",
"../modules/permission-management",
@ -19,7 +20,8 @@ $solutionPaths = @(
"../modules/background-jobs",
"../modules/account",
"../modules/cms-kit",
"../modules/blob-storing-database"
"../modules/blob-storing-database",
"../studio"
)
if ($full -eq "-f")

2
build/test-all.ps1

@ -7,7 +7,7 @@ $full = $args[0]
foreach ($solutionPath in $solutionPaths) {
$solutionAbsPath = (Join-Path $rootFolder $solutionPath)
Set-Location $solutionAbsPath
dotnet test --no-build --no-restore
dotnet test --no-build --no-restore --collect:"XPlat Code Coverage"
if (-Not $?) {
Write-Host ("Test failed for the solution: " + $solutionPath)
Set-Location $rootFolder

4
codecov.yml

@ -0,0 +1,4 @@
codecov:
branch: dev
require_ci_to_pass: yes
allow_coverage_offsets: true

2
common.props

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Version>5.0.0-beta.1</Version>
<Version>5.0.0-beta.2</Version>
<NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io/</PackageProjectUrl>

11
docs/en/Background-Jobs-Hangfire.md

@ -95,12 +95,21 @@ app.UseHangfireDashboard("/hangfire", new DashboardOptions
});
```
* `AbpHangfireAuthorizationFilter` is an implementation of an authorization filter.
#### AbpHangfireAuthorizationFilter
`AbpHangfireAuthorizationFilter` class has the following fields:
* **`enableTenant` (`bool`, default: `false`):** Enables/disables accessing the Hangfire dashboard on tenant users.
* **`requiredPermissionName` (`string`, default: `null`):** Hangfire dashboard is accessible only if the current user has the specified permission. In this case, if we specify a permission name, we don't need to set `enableTenant` `true` because the permission system already does it.
If you want to require an additional permission, you can pass it into the constructor as below:
```csharp
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter("MyHangFireDashboardPermissionName") }
AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter(requiredPermissionName: "MyHangFireDashboardPermissionName") }
});
```

99
docs/en/Background-Workers-Hangfire.md

@ -0,0 +1,99 @@
# Hangfire Background Worker Manager
[Hangfire](https://https://www.hangfire.io/) is an advanced background jobs and worker manager. You can integrate Hangfire with the ABP Framework to use it instead of the [default background worker manager](Background-Workers.md).
The major advantage is that you can use the same server farm to manage your Background Jobs and Workers, as well as leverage the advanced scheduling that is available from Hangfire for [Recurring Jobs](https://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html?highlight=recurring), aka Background Workers.
## Installation
It is suggested to use the [ABP CLI](CLI.md) to install this package.
### Using the ABP CLI
Open a command line window in the folder of the project (.csproj file) and type the following command:
````bash
abp add-package Volo.Abp.BackgroundWorkers.Hangfire
````
### Manual Installation
If you want to manually install;
1. Add the [Volo.Abp.BackgroundWorkers.Hangfire](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Hangfire) NuGet package to your project:
````
Install-Package Volo.Abp.BackgroundWorkers.Hangfire
````
2. Add the `AbpBackgroundWorkersHangfireModule` to the dependency list of your module:
````csharp
[DependsOn(
//...other dependencies
typeof(AbpBackgroundWorkersHangfireModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
````
> Hangfire background worker integration provides an adapter `HangfirePeriodicBackgroundWorkerAdapter` to automatically load any `PeriodicBackgroundWorkerBase` and `AsyncPeriodicBackgroundWorkerBase` derived classes as `IHangfireBackgroundWorker` instances. This allows you to still to easily switch over to use Hangfire as the background manager even you have existing background workers that are based on the [default background workers implementation](Background-Workers.md).
## Create a Background Worker
`HangfireBackgroundWorkerBase` is an easy way to create a background worker.
```` csharp
public class MyLogWorker : HangfireBackgroundWorkerBase
{
public MyLogWorker()
{
RecurringJobId = nameof(MyLogWorker);
CronExpression = Cron.Daily();
}
public override Task DoWorkAsync()
{
Logger.LogInformation("Executed MyLogWorker..!");
return Task.CompletedTask;
}
}
````
* **RecurringJobId** Is an optional parameter, see [Hangfire document](https://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html)
* **CronExpression** Is a CRON expression, see [CRON expression](https://en.wikipedia.org/wiki/Cron#CRON_expression)
> You can directly implement the `IHangfireBackgroundWorker`, but `HangfireBackgroundWorkerBase` provides some useful properties like Logger.
## Register BackgroundWorkerManager
After creating a background worker class, you should add it to the `IBackgroundWorkerManager`. The most common place is the `OnApplicationInitialization` method of your module class:
```` csharp
[DependsOn(typeof(AbpBackgroundWorkersModule))]
public class MyModule : AbpModule
{
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
context.AddBackgroundWorker<MyLogWorker>();
}
}
````
`context.AddBackgroundWorker(...)` is a shortcut extension method for the expression below:
```` csharp
context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.Add(
context
.ServiceProvider
.GetRequiredService<MyLogWorker>()
);
````
So, it resolves the given background worker and adds to the `IBackgroundWorkerManager`.
While we generally add workers in OnApplicationInitialization, there are no restrictions on that. You can inject IBackgroundWorkerManager anywhere and add workers at runtime. Background worker manager will stop and release all the registered workers when your application is being shut down.

11
docs/en/Background-Workers.md

@ -131,10 +131,15 @@ If that's a problem for your workers, you have two options;
* Disable the background worker system using the `AbpBackgroundWorkerOptions` described above, for all the application instances, except one of them.
* Disable the background worker system for all the application instances and create another special application that runs on a single server and execute the workers.
## Quartz Integration
## Integrations
ABP Framework's background worker system is good to implement periodic tasks. However, you may want to use an advanced task scheduler like [Quartz](https://www.quartz-scheduler.net/). See the community contributed [quartz integration](Background-Workers-Quartz.md) for the background workers.
Background worker system is extensible and you can change the default background worker manager with your own implementation or on of the pre-built integrations.
See pre-built worker manager alternatives:
* [Quartz Background Worker Manager](Background-Workers-Quartz.md)
* [Hangfire Background Worker Manager](Background-Workers-Hangfire.md)
## See Also
* [Quartz Integration for the background workers](Background-Workers-Quartz.md)
* [Background Jobs](Background-Jobs.md)

7
docs/en/Blog-Posts/2021-10-05 v5_0_Beta1/POST.md

@ -1,6 +1,6 @@
# ABP Platform 5.0 Beta 1 Has Been Released
Today, we are excited to release the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) version **5.0 Beta 1**. This blog post introduces the new features and important changes in this new version.
Today, we are excited to release the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) version **5.0 Beta**. This blog post introduces the new features and important changes in this new version.
> **The planned release date for the [5.0.0 Release Candidate](https://github.com/abpframework/abp/milestone/51) version is November, 2021**.
@ -34,10 +34,13 @@ See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all t
### Visual Studio Upgrade
As .NET 6 is a preview version you need to make changes on your current Visual Studio. If you want to run a .NET 6 project on Visual Studio 2019, you need to enable the `Use Previews of the .NET SDK` option from Visual Studio 2019 options. See the screenshot:
As .NET 6 is a preview version you need to make changes on the Visual Studio 2019.
If you want to run a .NET 6 project on Visual Studio 2019, you need to install the latest .NET SDK 6 from https://dotnet.microsoft.com/download/dotnet/6.0
and also enable the `Use Previews of the .NET SDK` option from Visual Studio 2019 options. See the screenshot:
![Enable Using Previews of the .NET SDK ](use-preview-visual-studio.png)
Alternatively you can download the latest Visual Studio 2022 preview to run/create the .NET 6 projects. We have tested the ABP solution with the Visual Studio 2022 `17.0.0 Preview 4.1`. Check out https://visualstudio.microsoft.com/vs/preview/ for more information.
### Migration Notes & Breaking Changes

53
docs/en/Distributed-Event-Bus.md

@ -302,55 +302,4 @@ namespace AbpDemo
}
````
This example uses the `AutoMap` attribute of the AutoMapper to configure the mapping. You could create a profile class instead. Please refer to the AutoMapper document for more options.
## Exception Handling
ABP provides exception handling and retries when an exception occurs, it will move to the dead letter queue after the retry fails.
Enable exception handling:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.EnabledErrorHandle = true;
options.UseRetryStrategy();
});
}
```
* `EnabledErrorHandle` is used to enable exception handing.
* `UseRetryStrategy` is used to enable retry.
When an exception occurs, it will retry every three seconds up to the maximum number of retries(default is 3) and move to dead letter queue, you can change the number of retries, retry interval and dead letter queue name:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.DeadLetterName = "dead_queue";
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### Error Handle Selector
By default all event types will be exception handling, you can use `ErrorHandleSelector` of `AbpEventBusOptions` to change it:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` actually a list of type predicate. You can write a lambda expression to define your filter.
### Customize Exception Handling
ABP defines the `IEventErrorHandler` interface and implemented by the provider, you can replace it via [dependency injection](Dependency-Injection.md)
This example uses the `AutoMap` attribute of the AutoMapper to configure the mapping. You could create a profile class instead. Please refer to the AutoMapper document for more options.

50
docs/en/Local-Event-Bus.md

@ -143,7 +143,7 @@ namespace AbpDemo
{
public async Task HandleEventAsync(StockCountChangedEvent eventData)
{
//TODO: your code that does somthing on the event
//TODO: your code that does something on the event
}
}
}
@ -158,52 +158,6 @@ If you perform **database operations** and use the [repositories](Repositories.m
> The handler class must be registered to the dependency injection (DI). The sample above uses the `ITransientDependency` to accomplish it. See the [DI document](Dependency-Injection.md) for more options.
## Exception Handling
ABP provides exception handling and retries when an exception occurs.
Enable exception handling:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy();
});
}
```
When an exception occurs, it will retry every three seconds up to the maximum number of retries(default is 3) and throw the original exception, you can change the number of retries and the retry interval:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### Error Handle Selector
By default all event types will be exception handling, you can use `ErrorHandleSelector` of `AbpEventBusOptions` to change it:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` actually a list of type predicate. You can write a lambda expression to define your filter.
### Customize Exception Handling
ABP defines the `IEventErrorHandler` interface and implemented by `LocalEventErrorHandler`, you can replace it via [dependency injection](Dependency-Injection.md)
### Transaction & Exception Behavior
When an event published, subscribed event handlers are immediately executed. So;
@ -272,4 +226,4 @@ The event types are;
Pre-build events are published when you save changes to the database;
* For EF Core, they are published on `DbContext.SaveChanges`.
* For MongoDB, they are published when you call repository's `InsertAsync`, `UpdateAsync` or `DeleteAsync` methods (since MongoDB has not a change tracking system).
* For MongoDB, they are published when you call repository's `InsertAsync`, `UpdateAsync` or `DeleteAsync` methods (since MongoDB has not a change tracking system).

3
docs/en/Module-Entity-Extensions.md

@ -491,3 +491,6 @@ Here, a few things you can do:
* You can override a domain or application service to perform custom logics with your new property.
* You can low level control how to add/render a field in the data table on the UI.
## See Also
* [Angular UI Extensions](UI/Angular/Extensions-Overall.md)

4
docs/en/Testing.md

@ -647,7 +647,7 @@ namespace MyProject.Issues
}
````
It's that simple. This test method tests everything, including the application service, EF Core mapping, object to object mapping and the repository implementation. In this way, you can fully test the Application Later and the Domain Layer of your solution.
It's that simple. This test method tests everything, including the application service, EF Core mapping, object to object mapping and the repository implementation. In this way, you can fully test the Application Layer and the Domain Layer of your solution.
## UI Tests
@ -670,4 +670,4 @@ See the following documents to learn Non Visual UI Testing;
Visual Tests are used to interact with the application UI just like a real user does. It fully tests the application, including the visual appearance of the pages and components.
Visual UI Testing is out of the scope for the ABP Framework. There are a lot of tooling in the industry (like [Selenium](https://www.selenium.dev/)) that you can use to test your application's UI.
Visual UI Testing is out of the scope for the ABP Framework. There are a lot of tooling in the industry (like [Selenium](https://www.selenium.dev/)) that you can use to test your application's UI.

4
docs/en/UI/Angular/Config-State-Service.md

@ -81,7 +81,7 @@ You can use the `getFeature` or `getFeature$` method of `ConfigStateService` to
```js
// this.config is instance of ConfigStateService
const enableLdapLogin = this.configStateService.getFeature("Account.EnableLdapLogin");
const enableLdapLogin = this.config.getFeature("Account.EnableLdapLogin");
// or
this.config.getFeature$("Account.EnableLdapLogin").subscribe(enableLdapLogin => {
@ -98,7 +98,7 @@ You can use the `getSetting` or `getSetting$` method of `ConfigStateService` to
```js
// this.config is instance of ConfigStateService
const twoFactorBehaviour = this.configStateService.getSetting("Abp.Identity.TwoFactor.Behaviour");
const twoFactorBehaviour = this.config.getSetting("Abp.Identity.TwoFactor.Behaviour");
// or
this.config.getSetting$("Abp.Identity.TwoFactor.Behaviour").subscribe(twoFactorBehaviour => {

10
docs/en/UI/Angular/Extensions-Overall.md

@ -0,0 +1,10 @@
## Angular UI Extensions
Angular UI extensions system allows you to add a new action to the actions menu, a new column to the data table, a new action to the toolbar of a page, and add a new field to the create and/or edit forms.
See the documents below for the details:
* [Entity Action Extensions](Entity-Action-Extensions.md)
* [Data Table Column (or Entity Prop) Extensions](Data-Table-Column-Extensions.md)
* [Page Toolbar Extension](Page-Toolbar-Extensions.md)
* [Dynamic Form (or Form Prop) Extensions](Dynamic-Form-Extensions.md)

8
docs/en/docs-nav.json

@ -235,6 +235,10 @@
{
"text": "Quartz Integration",
"path": "Background-Workers-Quartz.md"
},
{
"text": "Hangfire Integration",
"path": "Background-Workers-Hangfire.md"
}
]
},
@ -1057,6 +1061,10 @@
{
"text": "Extensions",
"items": [
{
"text": "Overall",
"path": "UI/Angular/Extensions-Overall.md"
},
{
"text": "Entity Action Extensions",
"path": "UI/Angular/Entity-Action-Extensions.md"

100
docs/zh-Hans/Background-Workers-Hangfire.md

@ -0,0 +1,100 @@
# Hangfire Background Worker Manager
[Hangfire](https://https://www.hangfire.io/)是一个高级的后台工作者管理. 你可以用ABP框架Hangfire集成代替[默认后台工作者管理](Background-Workers.md).
主要优点是你可以使用相同的服务器群来管理你的后台作业和工作线程以及利用 Hangfire 提供的[Recurring Jobs](https://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html?highlight=recurring)高级调度功能.
## 安装
建议使用[ABP CLI](CLI.md)安装包.
### 使用ABP CLI
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
````bash
abp add-package Volo.Abp.BackgroundWorkers.Hangfire
````
### 手动安装
如果你想手动安装;
1. 添加 [Volo.Abp.BackgroundWorkers.Hangfire](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Hangfire) NuGet包添加到你的项目:
````
Install-Package Volo.Abp.BackgroundWorkers.Hangfire
````
2. 添加 `AbpBackgroundWorkersHangfireModule` 到你的模块的依赖列表:
````csharp
[DependsOn(
//...other dependencies
typeof(AbpBackgroundWorkersHangfireModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
````
> Hangfire后台工作者集成提供了 `HangfirePeriodicBackgroundWorkerAdapter` 来适配 `PeriodicBackgroundWorkerBase` 和 `AsyncPeriodicBackgroundWorkerBase` 派生类. 所以你依然可以按照[后台工作者文档](Background-Workers.md)来定义后台作业.
## 创建后台工作者
`HangfireBackgroundWorkerBase` 是创建一个后台工作者简单的方法.
```` csharp
public class MyLogWorker : HangfireBackgroundWorkerBase
{
public MyLogWorker()
{
RecurringJobId = nameof(MyLogWorker);
CronExpression = Cron.Daily();
}
public override Task DoWorkAsync()
{
Logger.LogInformation("Executed MyLogWorker..!");
return Task.CompletedTask;
}
}
````
* **RecurringJobId** 是一个可选参数, 参阅 [Hangfire文档](https://docs.hangfire.io/en/latest/background-methods/performing-recurrent-tasks.html)
* **CronExpression** 是CRON表达式, 参阅 [CRON 表达式](https://en.wikipedia.org/wiki/Cron#CRON_expression)
> 你可以直接实现 `IHangfireBackgroundWorker`, 但是 `HangfireBackgroundWorkerBase` 提供了一些有用的属性,例如 `Logger`.
## 注册到后台工作者管理器
创建一个后台工作者后, 你应该添加到 `IBackgroundWorkerManager`, 最常用的地方是在你模块类的 `OnApplicationInitialization` 方法中:
```` csharp
[DependsOn(typeof(AbpBackgroundWorkersModule))]
public class MyModule : AbpModule
{
public override void OnApplicationInitialization(
ApplicationInitializationContext context)
{
context.AddBackgroundWorker<MyLogWorker>();
}
}
````
`context.AddBackgroundWorker(...)` 是一个是以下代码快捷的扩展方法:
```` csharp
context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.Add(
context
.ServiceProvider
.GetRequiredService<MyLogWorker>()
);
````
它解析给定的后台工作者并添加到 `IBackgroundWorkerManager`.
虽然我们通常在 `OnApplicationInitialization` 中添加后台工作者, 但对此没有限制. 你可以在任何地方注入 `IBackgroundWorkerManager` 并在运行时添加后台工作者.

8
docs/zh-Hans/Background-Workers.md

@ -128,11 +128,13 @@ context.ServiceProvider
* 使用上面提到的 `AbpBackgroundWorkerOptions` 禁用其他的后台工作者系统,只保留一个实例.
* 所有的应用程序都禁用后台工作者系统,创建一个特殊的应用程序在一个服务上运行执行工作者.
## Quartz 集成
## 集成
ABP框架的后台工作者系统可以很好的执行周期任务. 但是你可能需要使用更高级的任务调度,像[Quartz](https://www.quartz-scheduler.net/). 参阅社区贡献的[Quartz集成](Background-Workers-Quartz.md)
后台工作者系统是可扩展的,你可以更改默认的后台工作者管理器为你自己的实现,或者使用以下预构建的集成:
* [Quartz 后台工作者管理器](Background-Workers-Quartz.md)
* [Hangfire 后台工作者管理器](Background-Workers-Hangfire.md)
## 另请参阅
* [后台工作者的Quartz集成](Background-Workers-Quartz.md)
* [后台作业](Background-Jobs.md)

53
docs/zh-Hans/Distributed-Event-Bus.md

@ -299,55 +299,4 @@ namespace AbpDemo
}
````
此示例使用AutoMapper的 `AutoMap` 属性配置的映射. 你可以创建一个配置文件类代替. 请参阅AutoMapper文档了解更多选项.
## 异常处理
ABP提供了异常处理, 它会进行重试并且重试失败后移动到死信队列.
启用异常处理:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.EnabledErrorHandle = true;
options.UseRetryStrategy();
});
}
```
* `EnabledErrorHandle` 用于启用异常处理.
* `UseRetryStrategy` 用于启用重试.
当一个异常抛出,它会每3秒重试一次直到最大重试次数(默认是3)并且移动到错误队列, 你可以更改重试次数,重试间隔和死信队列名称:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.DeadLetterName = "dead_queue";
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### 错误处理选择器
默认所有的事件类型都会被处理, 你可以使用 `AbpEventBusOptions` 的 `ErrorHandleSelector` 来更改它:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` 实际上是一个类型类型谓词列表. 你可以编写lambda来定义你的过滤.
### 自定义异常处理
ABP定义了 `IEventErrorHandler` 接口并且由提供程序实现, 你可以通过[依赖注入](Dependency-Injection.md)替换它.
此示例使用AutoMapper的 `AutoMap` 属性配置的映射. 你可以创建一个配置文件类代替. 请参阅AutoMapper文档了解更多选项.

46
docs/zh-Hans/Local-Event-Bus.md

@ -158,52 +158,6 @@ namespace AbpDemo
如果您执行**数据库操作**并在事件处理程序中使用[仓储](Repositories.md),那么您可能需要创建一个[工作单元](Unit-Of-Work.md),因为一些存储库方法需要在**活动的工作单元**中工作. 确保处理方法设置为 `virtual`,并为该方法添加一个 `[UnitOfWork]` attribute. 或者手动使用 `IUnitOfWorkManager` 创建一个工作单元范围.
## 异常处理
ABP提供了异常处理, 当异常发现时它会进行重试.
启用异常处理:
```csharp
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy();
});
}
```
当一个异常抛出,它会每3秒重试一次直到最大重试次数(默认是3)并且移动抛出原始异常, 你可以更改重试次数和重试间隔和:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.UseRetryStrategy(retryStrategyOptions =>
{
retryStrategyOptions.IntervalMillisecond = 0;
retryStrategyOptions.MaxRetryAttempts = 1;
});
});
```
### 错误处理选择器
默认所有的事件类型都会被处理, 你可以使用 `AbpEventBusOptions` 的 `ErrorHandleSelector` 来更改它:
```csharp
PreConfigure<AbpEventBusOptions>(options =>
{
options.ErrorHandleSelector = type => type == typeof(MyExceptionHandleEventData);
});
```
`options.ErrorHandleSelector` 实际上是一个类型类型谓词列表. 你可以编写lambda来定义你的过滤.
### 自定义异常处理
ABP定义了 `IEventErrorHandler` 接口并且由 `LocalEventErrorHandler` 实现, 你可以通过[依赖注入](Dependency-Injection.md)替换它.
### 事务和异常行为
当一个事件发布,订阅的事件处理程序将立即执行.所以;

4
docs/zh-Hans/docs-nav.json

@ -176,6 +176,10 @@
{
"text": "Quartz 集成",
"path": "Background-Workers-Quartz.md"
},
{
"text": "Hangfire 集成",
"path": "Background-Workers-Hangfire.md"
}
]
}

30
framework/Volo.Abp.sln

@ -372,6 +372,7 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AzureServiceBus", "src\Volo.Abp.AzureServiceBus\Volo.Abp.AzureServiceBus.csproj", "{808EC18E-C8CC-4F5C-82B6-984EADBBF85D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Azure", "src\Volo.Abp.EventBus.Azure\Volo.Abp.EventBus.Azure.csproj", "{FB27F78E-F10E-4810-9B8E-BCD67DCFC8A2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Authorization.Abstractions", "src\Volo.Abp.Authorization.Abstractions\Volo.Abp.Authorization.Abstractions.csproj", "{87B0C2A8-FE95-4779-8B9C-2181AA52B3FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Core", "src\Volo.Abp.TextTemplating.Core\Volo.Abp.TextTemplating.Core.csproj", "{184E859A-282D-44D7-B8E9-FEA874644013}"
@ -390,13 +391,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.IdentityModel.Test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", "test\Volo.Abp.Threading.Tests\Volo.Abp.Threading.Tests.csproj", "{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EventBus.Boxes", "src\Volo.Abp.EventBus.Boxes\Volo.Abp.EventBus.Boxes.csproj", "{6E289F31-7924-418B-9DAC-62A7CFADF916}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking", "src\Volo.Abp.DistributedLocking\Volo.Abp.DistributedLocking.csproj", "{9A7EEA08-15BE-476D-8168-53039867038E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Auditing.Contracts", "src\Volo.Abp.Auditing.Contracts\Volo.Abp.Auditing.Contracts.csproj", "{508B6355-AD28-4E60-8549-266D21DBF2CF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Http.Client.Web", "src\Volo.Abp.Http.Client.Web\Volo.Abp.Http.Client.Web.csproj", "{F7407459-8AFA-45E4-83E9-9BB01412CC08}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking.Abstractions", "src\Volo.Abp.DistributedLocking.Abstractions\Volo.Abp.DistributedLocking.Abstractions.csproj", "{CA805B77-D50C-431F-B3CB-1111C9C6E807}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.DistributedLocking.Abstractions.Tests", "test\Volo.Abp.DistributedLocking.Abstractions.Tests\Volo.Abp.DistributedLocking.Abstractions.Tests.csproj", "{C4F54FB5-C828-414D-BA03-E8E7A10C784D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundWorkers.Hangfire", "src\Volo.Abp.BackgroundWorkers.Hangfire\Volo.Abp.BackgroundWorkers.Hangfire.csproj", "{E5FCE710-C5A3-4F94-B9C9-BD1E99252BFB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1171,10 +1177,6 @@ Global
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.Build.0 = Release|Any CPU
{6E289F31-7924-418B-9DAC-62A7CFADF916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E289F31-7924-418B-9DAC-62A7CFADF916}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E289F31-7924-418B-9DAC-62A7CFADF916}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E289F31-7924-418B-9DAC-62A7CFADF916}.Release|Any CPU.Build.0 = Release|Any CPU
{9A7EEA08-15BE-476D-8168-53039867038E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A7EEA08-15BE-476D-8168-53039867038E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A7EEA08-15BE-476D-8168-53039867038E}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -1187,6 +1189,18 @@ Global
{F7407459-8AFA-45E4-83E9-9BB01412CC08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7407459-8AFA-45E4-83E9-9BB01412CC08}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7407459-8AFA-45E4-83E9-9BB01412CC08}.Release|Any CPU.Build.0 = Release|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA805B77-D50C-431F-B3CB-1111C9C6E807}.Release|Any CPU.Build.0 = Release|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4F54FB5-C828-414D-BA03-E8E7A10C784D}.Release|Any CPU.Build.0 = Release|Any CPU
{E5FCE710-C5A3-4F94-B9C9-BD1E99252BFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5FCE710-C5A3-4F94-B9C9-BD1E99252BFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5FCE710-C5A3-4F94-B9C9-BD1E99252BFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5FCE710-C5A3-4F94-B9C9-BD1E99252BFB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1384,10 +1398,12 @@ Global
{90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{40C6740E-BFCA-4D37-8344-3D84E2044BB2} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{6E289F31-7924-418B-9DAC-62A7CFADF916} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{9A7EEA08-15BE-476D-8168-53039867038E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{508B6355-AD28-4E60-8549-266D21DBF2CF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{F7407459-8AFA-45E4-83E9-9BB01412CC08} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{CA805B77-D50C-431F-B3CB-1111C9C6E807} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{C4F54FB5-C828-414D-BA03-E8E7A10C784D} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{E5FCE710-C5A3-4F94-B9C9-BD1E99252BFB} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

34
framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/DependencyInjection/AbpWebAssemblyConventionalRegistrar.cs

@ -5,39 +5,21 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.DependencyInjection
{
public class AbpWebAssemblyConventionalRegistrar : ConventionalRegistrarBase
public class AbpWebAssemblyConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
if (!IsComponent(type))
{
return;
}
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
TriggerServiceExposing(services, type, serviceTypes);
foreach (var serviceType in serviceTypes)
{
services.Add(
ServiceDescriptor.Describe(
serviceType,
type,
ServiceLifetime.Transient
)
);
}
return !IsComponent(type) || base.IsConventionalRegistrationDisabled(type);
}
private static bool IsComponent(Type type)
{
return typeof(ComponentBase).IsAssignableFrom(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/AlertsDemo/AlertsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/AlertsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BadgesDemo/BadgesDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/BadgesDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BordersDemo/BordersDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/BordersDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/BreadcrumbsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/BreadcrumbsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/ButtonGroupsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ButtonGroupsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ButtonsDemo/ButtonsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ButtonsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CardsDemo/CardsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/CardsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CarouselDemo/CarouselDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/CarouselDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/CollapseDemo/CollapseDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/CollapseDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DropdownsDemo/DropdownsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/DropdownsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
var Model = new DropDownDemoDemoModel();

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/DynamicFormsDemo/DynamicFormsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/DynamicFormsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
var model = new DynamicFormsDemoModel();

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/FormElementsDemo/FormElementsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/FormElementsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
var model = new FormElementsDemoModel();

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/GridsDemo/GridsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/GridsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ListGroupsDemo/ListGroupsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ListGroupsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ModalsDemo/ModalsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ModalsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavbarsDemo/NavbarsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/NavbarsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/NavsDemo/NavsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/NavsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/PopoversDemo/PopoversDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/PopoversDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/ProgressBarsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/ProgressBarsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TablesDemo/TablesDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/TablesDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TabsDemo/TabsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/TabsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Views/Components/Themes/Shared/Demos/TooltipsDemo/TooltipsDemoViewComponent.cs

@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.Views.Components.Themes.S
{
public const string ViewPath = "/Views/Components/Themes/Shared/Demos/TooltipsDemo/Default.cshtml";
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View(ViewPath);
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpApplicationPath/AbpApplicationPathViewComponent.cs

@ -5,7 +5,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpApp
{
public class AbpApplicationPathViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
var applicationPath = ViewContext.HttpContext.Request.PathBase.Value;
var model = new AbpApplicationPathViewComponentModel

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpPageSearchBox/AbpPageSearchBoxViewComponent.cs

@ -4,7 +4,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPag
{
public class AbpPageSearchBoxViewComponent : AbpViewComponent
{
public IViewComponentResult Invoke()
public virtual IViewComponentResult Invoke()
{
return View("~/Pages/Shared/Components/AbpPageSearchBox/Default.cshtml");
}

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Shared/Components/AbpPageToolbar/AbpPageToolbarViewComponent.cs

@ -6,16 +6,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Shared.Components.AbpPag
{
public class AbpPageToolbarViewComponent : AbpViewComponent
{
private readonly IPageToolbarManager _toolbarManager;
protected IPageToolbarManager ToolbarManager { get; }
public AbpPageToolbarViewComponent(IPageToolbarManager toolbarManager)
{
_toolbarManager = toolbarManager;
ToolbarManager = toolbarManager;
}
public async Task<IViewComponentResult> InvokeAsync(string pageName)
public virtual async Task<IViewComponentResult> InvokeAsync(string pageName)
{
var items = await _toolbarManager.GetItemsAsync(pageName);
var items = await ToolbarManager.GetItemsAsync(pageName);
return View("~/Pages/Shared/Components/AbpPageToolbar/Default.cshtml", items);
}
}

41
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar.cs

@ -7,36 +7,11 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
{
public class AbpAspNetCoreMvcConventionalRegistrar : ConventionalRegistrarBase
public class AbpAspNetCoreMvcConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
if (!IsMvcService(type))
{
return;
}
var lifeTime = GetMvcServiceLifetime(type);
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
TriggerServiceExposing(services, type, serviceTypes);
foreach (var serviceType in serviceTypes)
{
services.Add(
ServiceDescriptor.Describe(
serviceType,
type,
lifeTime
)
);
}
return !IsMvcService(type) || base.IsConventionalRegistrationDisabled(type);
}
protected virtual bool IsMvcService(Type type)
@ -46,11 +21,6 @@ namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
IsViewComponent(type);
}
protected virtual ServiceLifetime GetMvcServiceLifetime(Type type)
{
return ServiceLifetime.Transient;
}
private static bool IsPageModel(Type type)
{
return typeof(PageModel).IsAssignableFrom(type) || type.IsDefined(typeof(PageModelAttribute), true);
@ -65,5 +35,10 @@ namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
{
return typeof(ViewComponent).IsAssignableFrom(type) || type.IsDefined(typeof(ViewComponentAttribute), true);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

36
framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalRConventionalRegistrar.cs

@ -5,39 +5,21 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.SignalR
{
public class AbpSignalRConventionalRegistrar : ConventionalRegistrarBase
public class AbpSignalRConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
if (!IsHub(type))
{
return;
}
var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
TriggerServiceExposing(services, type, serviceTypes);
foreach (var serviceType in serviceTypes)
{
services.Add(
ServiceDescriptor.Describe(
serviceType,
type,
ServiceLifetime.Transient
)
);
}
return !IsHub(type) || base.IsConventionalRegistrationDisabled(type);
}
private static bool IsHub(Type type)
{
return typeof(Hub).IsAssignableFrom(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

18
framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperConventionalRegistrar.cs

@ -3,12 +3,11 @@ using System.Linq;
using AutoMapper;
using AutoMapper.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AutoMapper
{
public class AbpAutoMapperConventionalRegistrar : ConventionalRegistrarBase
public class AbpAutoMapperConventionalRegistrar : DefaultConventionalRegistrar
{
protected readonly Type[] OpenTypes = {
typeof(IValueResolver<,,>),
@ -18,17 +17,14 @@ namespace Volo.Abp.AutoMapper
typeof(IMappingAction<,>)
};
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (IsConventionalRegistrationDisabled(type))
{
return;
}
return !OpenTypes.Any(type.ImplementsGenericInterface) || base.IsConventionalRegistrationDisabled(type);
}
if (type.IsClass && !type.IsAbstract && OpenTypes.Any(type.ImplementsGenericInterface))
{
services.TryAddTransient(type);
}
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return ServiceLifetime.Transient;
}
}
}

2
framework/src/Volo.Abp.BackgroundJobs/Volo.Abp.BackgroundJobs.csproj

@ -17,7 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BackgroundJobs.Abstractions\Volo.Abp.BackgroundJobs.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.BackgroundWorkers\Volo.Abp.BackgroundWorkers.csproj" />
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
<ProjectReference Include="..\Volo.Abp.DistributedLocking.Abstractions\Volo.Abp.DistributedLocking.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
</ItemGroup>

4
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobsModule.cs

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Guids;
using Volo.Abp.Modularity;
using Volo.Abp.Timing;
@ -11,7 +12,8 @@ namespace Volo.Abp.BackgroundJobs
typeof(AbpBackgroundJobsAbstractionsModule),
typeof(AbpBackgroundWorkersModule),
typeof(AbpTimingModule),
typeof(AbpGuidsModule)
typeof(AbpGuidsModule),
typeof(AbpDistributedLockingAbstractionsModule)
)]
public class AbpBackgroundJobsModule : AbpModule
{

103
framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.DistributedLocking;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
@ -12,19 +13,25 @@ namespace Volo.Abp.BackgroundJobs
{
public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroundJobWorker
{
protected const string DistributedLockName = "AbpBackgroundJobWorker";
protected AbpBackgroundJobOptions JobOptions { get; }
protected AbpBackgroundJobWorkerOptions WorkerOptions { get; }
protected IAbpDistributedLock DistributedLock { get; }
public BackgroundJobWorker(
AbpAsyncTimer timer,
IOptions<AbpBackgroundJobOptions> jobOptions,
IOptions<AbpBackgroundJobWorkerOptions> workerOptions,
IServiceScopeFactory serviceScopeFactory)
IServiceScopeFactory serviceScopeFactory,
IAbpDistributedLock distributedLock)
: base(
timer,
serviceScopeFactory)
{
DistributedLock = distributedLock;
WorkerOptions = workerOptions.Value;
JobOptions = jobOptions.Value;
Timer.Period = WorkerOptions.JobPollPeriod;
@ -32,57 +39,74 @@ namespace Volo.Abp.BackgroundJobs
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
var store = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobStore>();
var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount);
if (!waitingJobs.Any())
await using (var handler = await DistributedLock.TryAcquireAsync(DistributedLockName, cancellationToken: StoppingToken))
{
return;
}
var jobExecuter = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobExecuter>();
var clock = workerContext.ServiceProvider.GetRequiredService<IClock>();
var serializer = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobSerializer>();
foreach (var jobInfo in waitingJobs)
{
jobInfo.TryCount++;
jobInfo.LastTryTime = clock.Now;
try
if (handler != null)
{
var jobConfiguration = JobOptions.GetJob(jobInfo.JobName);
var jobArgs = serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType);
var context = new JobExecutionContext(workerContext.ServiceProvider, jobConfiguration.JobType, jobArgs);
var store = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobStore>();
try
{
await jobExecuter.ExecuteAsync(context);
var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount);
await store.DeleteAsync(jobInfo.Id);
if (!waitingJobs.Any())
{
return;
}
catch (BackgroundJobExecutionException)
var jobExecuter = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobExecuter>();
var clock = workerContext.ServiceProvider.GetRequiredService<IClock>();
var serializer = workerContext.ServiceProvider.GetRequiredService<IBackgroundJobSerializer>();
foreach (var jobInfo in waitingJobs)
{
var nextTryTime = CalculateNextTryTime(jobInfo, clock);
jobInfo.TryCount++;
jobInfo.LastTryTime = clock.Now;
if (nextTryTime.HasValue)
try
{
jobInfo.NextTryTime = nextTryTime.Value;
var jobConfiguration = JobOptions.GetJob(jobInfo.JobName);
var jobArgs = serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType);
var context = new JobExecutionContext(
workerContext.ServiceProvider,
jobConfiguration.JobType,
jobArgs);
try
{
await jobExecuter.ExecuteAsync(context);
await store.DeleteAsync(jobInfo.Id);
}
catch (BackgroundJobExecutionException)
{
var nextTryTime = CalculateNextTryTime(jobInfo, clock);
if (nextTryTime.HasValue)
{
jobInfo.NextTryTime = nextTryTime.Value;
}
else
{
jobInfo.IsAbandoned = true;
}
await TryUpdateAsync(store, jobInfo);
}
}
else
catch (Exception ex)
{
Logger.LogException(ex);
jobInfo.IsAbandoned = true;
await TryUpdateAsync(store, jobInfo);
}
await TryUpdateAsync(store, jobInfo);
}
}
catch (Exception ex)
else
{
Logger.LogException(ex);
jobInfo.IsAbandoned = true;
await TryUpdateAsync(store, jobInfo);
try
{
await Task.Delay(WorkerOptions.JobPollPeriod * 12, StoppingToken);
}
catch (TaskCanceledException) { }
}
}
}
@ -101,7 +125,8 @@ namespace Volo.Abp.BackgroundJobs
protected virtual DateTime? CalculateNextTryTime(BackgroundJobInfo jobInfo, IClock clock)
{
var nextWaitDuration = WorkerOptions.DefaultFirstWaitDuration * (Math.Pow(WorkerOptions.DefaultWaitFactor, jobInfo.TryCount - 1));
var nextWaitDuration = WorkerOptions.DefaultFirstWaitDuration *
(Math.Pow(WorkerOptions.DefaultWaitFactor, jobInfo.TryCount - 1));
var nextTryDate = jobInfo.LastTryTime?.AddSeconds(nextWaitDuration) ??
clock.Now.AddSeconds(nextWaitDuration);
@ -113,4 +138,4 @@ namespace Volo.Abp.BackgroundJobs
return nextTryDate;
}
}
}
}

3
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

2
framework/src/Volo.Abp.EventBus.Boxes/FodyWeavers.xsd → framework/src/Volo.Abp.BackgroundWorkers.Hangfire/FodyWeavers.xsd

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">

7
framework/src/Volo.Abp.EventBus.Boxes/Volo.Abp.EventBus.Boxes.csproj → framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo.Abp.BackgroundWorkers.Hangfire.csproj

@ -5,8 +5,8 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.EventBus.Boxes</AssemblyName>
<PackageId>Volo.Abp.EventBus.Boxes</PackageId>
<AssemblyName>Volo.Abp.BackgroundWorkers.Hangfire</AssemblyName>
<PackageId>Volo.Abp.BackgroundWorkers.Hangfire</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
@ -16,8 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BackgroundWorkers\Volo.Abp.BackgroundWorkers.csproj" />
<ProjectReference Include="..\Volo.Abp.DistributedLocking\Volo.Abp.DistributedLocking.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.Hangfire\Volo.Abp.Hangfire.csproj" />
</ItemGroup>
</Project>

36
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs

@ -0,0 +1,36 @@
using System;
using Hangfire;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Hangfire;
using Volo.Abp.Modularity;
namespace Volo.Abp.BackgroundWorkers.Hangfire
{
[DependsOn(
typeof(AbpBackgroundWorkersModule),
typeof(AbpHangfireModule))]
public class AbpBackgroundWorkerHangfireModule : AbpModule
{
public override void OnPreApplicationInitialization(ApplicationInitializationContext context)
{
var options = context.ServiceProvider.GetRequiredService<IOptions<AbpBackgroundWorkerOptions>>().Value;
if (!options.IsEnabled)
{
var hangfireOptions = context.ServiceProvider.GetRequiredService<IOptions<AbpHangfireOptions>>().Value;
hangfireOptions.BackgroundJobServerFactory = CreateOnlyEnqueueJobServer;
}
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddSingleton(typeof(HangfirePeriodicBackgroundWorkerAdapter<>));
}
private BackgroundJobServer CreateOnlyEnqueueJobServer(IServiceProvider serviceProvider)
{
serviceProvider.GetRequiredService<JobStorage>();
return null;
}
}
}

13
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs

@ -0,0 +1,13 @@
using System.Threading.Tasks;
namespace Volo.Abp.BackgroundWorkers.Hangfire
{
public abstract class HangfireBackgroundWorkerBase : BackgroundWorkerBase, IHangfireBackgroundWorker
{
public string RecurringJobId { get; set; }
public string CronExpression { get; set; }
public abstract Task DoWorkAsync();
}
}

91
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs

@ -0,0 +1,91 @@
using System;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Hangfire;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers.Hangfire
{
[Dependency(ReplaceServices = true)]
public class HangfireBackgroundWorkerManager : IBackgroundWorkerManager, ISingletonDependency
{
public Task StartAsync(CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
public void Add(IBackgroundWorker worker)
{
if (worker is IHangfireBackgroundWorker hangfireBackgroundWorker)
{
if (hangfireBackgroundWorker.RecurringJobId.IsNullOrWhiteSpace())
{
RecurringJob.AddOrUpdate(() => hangfireBackgroundWorker.DoWorkAsync(),
hangfireBackgroundWorker.CronExpression);
}
else
{
RecurringJob.AddOrUpdate(hangfireBackgroundWorker.RecurringJobId,() => hangfireBackgroundWorker.DoWorkAsync(),
hangfireBackgroundWorker.CronExpression);
}
}
else
{
int? period;
if (worker is AsyncPeriodicBackgroundWorkerBase or PeriodicBackgroundWorkerBase)
{
var timer = (AbpTimer) worker.GetType()
.GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker);
period = timer?.Period;
}
else
{
return;
}
if (period == null)
{
return;
}
var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(worker.GetType());
var workerAdapter = Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker;
RecurringJob.AddOrUpdate(() => workerAdapter.DoWorkAsync(), GetCron(period.Value));
}
}
protected virtual string GetCron(int period)
{
var time = TimeSpan.FromMilliseconds(period);
string cron;
if (time.TotalSeconds <= 59)
{
cron = $"*/{time.TotalSeconds} * * * * *";
}
else if (time.TotalMinutes <= 59)
{
cron = $"*/{time.TotalMinutes} * * * *";
}
else if (time.TotalHours <= 23)
{
cron = $"0 */{time.TotalHours} * * *";
}
else
{
cron = $"0 0 */{time.TotalDays} * *";
}
return cron;
}
}
}

36
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfirePeriodicBackgroundWorkerAdapter.cs

@ -0,0 +1,36 @@
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers.Hangfire
{
public class HangfirePeriodicBackgroundWorkerAdapter<TWorker> : HangfireBackgroundWorkerBase
where TWorker : IBackgroundWorker
{
private readonly MethodInfo _doWorkAsyncMethod;
private readonly MethodInfo _doWorkMethod;
public HangfirePeriodicBackgroundWorkerAdapter()
{
_doWorkAsyncMethod =
typeof(TWorker).GetMethod("DoWorkAsync", BindingFlags.Instance | BindingFlags.NonPublic);
_doWorkMethod = typeof(TWorker).GetMethod("DoWork", BindingFlags.Instance | BindingFlags.NonPublic);
}
public override async Task DoWorkAsync()
{
var workerContext = new PeriodicBackgroundWorkerContext(ServiceProvider);
var worker = ServiceProvider.GetRequiredService<TWorker>();
switch (worker)
{
case AsyncPeriodicBackgroundWorkerBase asyncPeriodicBackgroundWorker:
await (Task) _doWorkAsyncMethod.Invoke(asyncPeriodicBackgroundWorker, new object[] {workerContext});
break;
case PeriodicBackgroundWorkerBase periodicBackgroundWorker:
_doWorkMethod.Invoke(periodicBackgroundWorker, new object[] {workerContext});
break;
}
}
}
}

15
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/IHangfireBackgroundWorker.cs

@ -0,0 +1,15 @@
using System.Threading.Tasks;
namespace Volo.Abp.BackgroundWorkers.Hangfire
{
public interface IHangfireBackgroundWorker : IBackgroundWorker
{
string RecurringJobId { get; set; }
string CronExpression { get; set; }
Task DoWorkAsync();
}
}

23
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpQuartzConventionalRegistrar.cs

@ -1,27 +1,22 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers.Quartz
{
public class AbpQuartzConventionalRegistrar : DefaultConventionalRegistrar
{
public override void AddType(IServiceCollection services, Type type)
protected override bool IsConventionalRegistrationDisabled(Type type)
{
if (!typeof(IQuartzBackgroundWorker).IsAssignableFrom(type))
{
return;
}
var dependencyAttribute = GetDependencyAttributeOrNull(type);
var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute);
return !typeof(IQuartzBackgroundWorker).IsAssignableFrom(type) || base.IsConventionalRegistrationDisabled(type);
}
if (lifeTime == null)
protected override List<Type> GetExposedServiceTypes(Type type)
{
return new List<Type>()
{
return;
}
services.Add(ServiceDescriptor.Describe(typeof(IQuartzBackgroundWorker), type, lifeTime.Value));
typeof(IQuartzBackgroundWorker)
};
}
}
}

11
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkerBase.cs

@ -21,6 +21,15 @@ namespace Volo.Abp.BackgroundWorkers
protected ILoggerFactory LoggerFactory => LazyServiceProvider.LazyGetRequiredService<ILoggerFactory>();
protected ILogger Logger => LazyServiceProvider.LazyGetService<ILogger>(provider => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance);
protected CancellationTokenSource StoppingTokenSource { get; }
protected CancellationToken StoppingToken { get; }
public BackgroundWorkerBase()
{
StoppingTokenSource = new CancellationTokenSource();
StoppingToken = StoppingTokenSource.Token;
}
public virtual Task StartAsync(CancellationToken cancellationToken = default)
{
@ -31,6 +40,8 @@ namespace Volo.Abp.BackgroundWorkers
public virtual Task StopAsync(CancellationToken cancellationToken = default)
{
Logger.LogDebug("Stopped background worker: " + ToString());
StoppingTokenSource.Cancel();
StoppingTokenSource.Dispose();
return Task.CompletedTask;
}

1
framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs

@ -504,6 +504,7 @@ namespace Volo.Abp.BlazoriseUI
{
await GetEntitiesAsync();
await InvokeAsync(StateHasChanged);
await Notify.Success(L["SuccessfullyDeleted"]);
}
protected virtual string GetDeleteConfirmationMessage(TListViewModel entity)

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Auth/LoginInfo.cs

@ -12,5 +12,7 @@ namespace Volo.Abp.Cli.Auth
public string EmailAddress { get; set; }
public string Organization { get; set; }
public bool HasSourceCodeAccess { get; set; }
}
}

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/DefaultDotNetProjectBuilder.cs

@ -9,6 +9,13 @@ namespace Volo.Abp.Cli.Build
{
public class DefaultDotNetProjectBuilder : IDotNetProjectBuilder, ITransientDependency
{
public ICmdHelper CmdHelper { get; }
public DefaultDotNetProjectBuilder(ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
}
public List<string> BuildProjects(List<DotNetProjectInfo> projects, string arguments)
{
var builtProjects = new ConcurrentBag<string>();

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs

@ -24,17 +24,20 @@ namespace Volo.Abp.Cli
protected ICommandSelector CommandSelector { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected NuGetService NuGetService { get; }
public ICmdHelper CmdHelper { get; }
public CliService(
ICommandLineArgumentParser commandLineArgumentParser,
ICommandSelector commandSelector,
IServiceScopeFactory serviceScopeFactory,
NuGetService nugetService)
NuGetService nugetService,
ICmdHelper cmdHelper)
{
CommandLineArgumentParser = commandLineArgumentParser;
CommandSelector = commandSelector;
ServiceScopeFactory = serviceScopeFactory;
NuGetService = nugetService;
CmdHelper = cmdHelper;
Logger = NullLogger<CliService>.Instance;
}
@ -42,7 +45,7 @@ namespace Volo.Abp.Cli
public async Task RunAsync(string[] args)
{
Logger.LogInformation("ABP CLI (https://abp.io)");
var commandLineArgs = CommandLineArgumentParser.Parse(args);
#if !DEBUG
@ -147,7 +150,7 @@ namespace Volo.Abp.Cli
await RunInternalAsync(args);
}
}
private async Task RunInternalAsync(CommandLineArgs commandLineArgs)
{
var commandType = CommandSelector.Select(commandLineArgs);
@ -203,7 +206,7 @@ namespace Volo.Abp.Cli
{
SemanticVersion currentCliVersion = default;
var consoleOutput = new StringReader(CmdHelper.RunCmdAndGetOutput($"dotnet tool list -g"));
var consoleOutput = new StringReader(CmdHelper.RunCmdAndGetOutput($"dotnet tool list -g", out int exitCode));
string line;
while ((line = await consoleOutput.ReadLineAsync()) != null)
{

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs

@ -4,19 +4,18 @@ namespace Volo.Abp.Cli
{
public static class CliUrls
{
#if DEBUG
/*
public const string WwwAbpIo = WwwAbpIoDevelopment;
public const string AccountAbpIo = AccountAbpIoDevelopment;
public const string NuGetRootPath = NuGetRootPathDevelopment;
#else
*/
public const string WwwAbpIo = WwwAbpIoProduction;
public const string AccountAbpIo = AccountAbpIoProduction;
public const string NuGetRootPath = NuGetRootPathProduction;
#endif
public const string WwwAbpIoProduction = "https://abp.io/";
public const string AccountAbpIoProduction = "https://account.abp.io/";

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs

@ -18,7 +18,7 @@ namespace Volo.Abp.Cli.Commands
public ILogger<AddModuleCommand> Logger { get; set; }
protected SolutionModuleAdder SolutionModuleAdder { get; }
public SolutionAbpVersionFinder SolutionAbpVersionFinder { get; }
public SolutionPackageVersionFinder SolutionPackageVersionFinder { get; }
public AddModuleInfoOutput LastAddedModuleInfo
{
@ -33,10 +33,10 @@ namespace Volo.Abp.Cli.Commands
}
}
public AddModuleCommand(SolutionModuleAdder solutionModuleAdder, SolutionAbpVersionFinder solutionAbpVersionFinder)
public AddModuleCommand(SolutionModuleAdder solutionModuleAdder, SolutionPackageVersionFinder solutionPackageVersionFinder)
{
SolutionModuleAdder = solutionModuleAdder;
SolutionAbpVersionFinder = solutionAbpVersionFinder;
SolutionPackageVersionFinder = solutionPackageVersionFinder;
Logger = NullLogger<AddModuleCommand>.Instance;
}
@ -62,7 +62,7 @@ namespace Volo.Abp.Cli.Commands
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
if (version == null)
{
version = SolutionAbpVersionFinder.Find(solutionFile);
version = SolutionPackageVersionFinder.Find(solutionFile);
}
var moduleInfo = await SolutionModuleAdder.AddAsync(

12
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs

@ -12,10 +12,12 @@ namespace Volo.Abp.Cli.Commands
{
public class CreateMigrationAndRunMigratorCommand : IConsoleCommand, ITransientDependency
{
public ICmdHelper CmdHelper { get; }
public ILogger<CreateMigrationAndRunMigratorCommand> Logger { get; set; }
public CreateMigrationAndRunMigratorCommand()
public CreateMigrationAndRunMigratorCommand(ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
Logger = NullLogger<CreateMigrationAndRunMigratorCommand>.Instance;
}
@ -98,7 +100,7 @@ namespace Volo.Abp.Cli.Commands
return Path.GetFileName(dbContext).RemovePostFix(".cs");
}
private static string AddMigrationAndGetOutput(string dbMigrationsFolder, string dbContext, string outputDirectory)
private string AddMigrationAndGetOutput(string dbMigrationsFolder, string dbContext, string outputDirectory)
{
var dbContextOption = string.IsNullOrWhiteSpace(dbContext)
? string.Empty
@ -107,12 +109,12 @@ namespace Volo.Abp.Cli.Commands
var addMigrationCmd = $"cd \"{dbMigrationsFolder}\" && " +
$"dotnet ef migrations add Initial --output-dir {outputDirectory} {dbContextOption}";
return CmdHelper.RunCmdAndGetOutput(addMigrationCmd);
return CmdHelper.RunCmdAndGetOutput(addMigrationCmd, out int exitCode);
}
private static bool IsDotNetEfToolInstalled()
private bool IsDotNetEfToolInstalled()
{
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g");
var output = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g", out int exitCode);
return output.Contains("dotnet-ef");
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -35,8 +35,9 @@ namespace Volo.Abp.Cli.Commands
public NewCommand(TemplateProjectBuilder templateProjectBuilder
, ITemplateInfoProvider templateInfoProvider,
ConnectionStringProvider connectionStringProvider)
: base(connectionStringProvider)
ConnectionStringProvider connectionStringProvider,
ICmdHelper cmdHelper)
: base(connectionStringProvider, cmdHelper)
{
TemplateProjectBuilder = templateProjectBuilder;
TemplateInfoProvider = templateInfoProvider;

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs

@ -18,11 +18,13 @@ namespace Volo.Abp.Cli.Commands
public abstract class ProjectCreationCommandBase
{
public ConnectionStringProvider ConnectionStringProvider { get; }
public ICmdHelper CmdHelper { get; }
public ILogger<NewCommand> Logger { get; set; }
public ProjectCreationCommandBase(ConnectionStringProvider connectionStringProvider)
public ProjectCreationCommandBase(ConnectionStringProvider connectionStringProvider, ICmdHelper cmdHelper)
{
ConnectionStringProvider = connectionStringProvider;
CmdHelper = cmdHelper;
Logger = NullLogger<NewCommand>.Instance;
}
@ -204,6 +206,10 @@ namespace Volo.Abp.Cli.Commands
bool isTiered,
CommandLineArgs commandLineArgs)
{
#if DEBUG
return;
#endif
if (AppTemplateBase.IsAppTemplate(template))
{
var isCommercial = template == AppProTemplate.TemplateName;

22
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs

@ -15,13 +15,15 @@ namespace Volo.Abp.Cli.Commands
{
public class SuiteCommand : IConsoleCommand, ITransientDependency
{
public ICmdHelper CmdHelper { get; }
private readonly AbpNuGetIndexUrlService _nuGetIndexUrlService;
private readonly NuGetService _nuGetService;
private const string SuitePackageName = "Volo.Abp.Suite";
public ILogger<SuiteCommand> Logger { get; set; }
public SuiteCommand(AbpNuGetIndexUrlService nuGetIndexUrlService, NuGetService nuGetService)
public SuiteCommand(AbpNuGetIndexUrlService nuGetIndexUrlService, NuGetService nuGetService, ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
_nuGetIndexUrlService = nuGetIndexUrlService;
_nuGetService = nuGetService;
Logger = NullLogger<SuiteCommand>.Instance;
@ -71,7 +73,7 @@ namespace Volo.Abp.Cli.Commands
private string GetCurrentSuiteVersion()
{
var dotnetToolList = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g");
var dotnetToolList = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g", out int exitCode);
var suiteLine = dotnetToolList.Split(Environment.NewLine)
.FirstOrDefault(l => l.ToLower().StartsWith("volo.abp.suite "));
@ -127,11 +129,11 @@ namespace Volo.Abp.Cli.Commands
versionOption = $" --version {version}";
}
var result = CmdHelper.RunCmd(
$"dotnet tool install {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g"
CmdHelper.RunCmd(
$"dotnet tool install {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g", out int exitCode
);
if (result == 0)
if (exitCode == 0)
{
Logger.LogInformation("ABP Suite has been successfully installed.");
Logger.LogInformation("You can run it with the CLI command \"abp suite\"");
@ -197,11 +199,11 @@ namespace Volo.Abp.Cli.Commands
versionOption = $" --version {version}";
}
var result = CmdHelper.RunCmd(
$"dotnet tool update {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g"
CmdHelper.RunCmd(
$"dotnet tool update {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g", out int exitCode
);
if (result != 0)
if (exitCode != 0)
{
ShowSuiteManualUpdateCommand();
}
@ -230,7 +232,7 @@ namespace Volo.Abp.Cli.Commands
Logger.LogError("dotnet tool update -g Volo.Abp.Suite --add-source https://nuget.abp.io/<your-private-key>/v3/index.json");
}
private static void RemoveSuite()
private void RemoveSuite()
{
CmdHelper.RunCmd("dotnet tool uninstall " + SuitePackageName + " -g");
}
@ -275,7 +277,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine(" abp suite");
sb.AppendLine(" abp suite install");
sb.AppendLine(" abp suite install --preview");
sb.AppendLine(" abp suite install --version 4.2.2");
sb.AppendLine(" abp suite install --version 4.2.2");
sb.AppendLine(" abp suite update");
sb.AppendLine(" abp suite update --preview");
sb.AppendLine(" abp suite remove");

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs

@ -16,14 +16,16 @@ namespace Volo.Abp.Cli.LIbs
{
public class InstallLibsService : IInstallLibsService, ITransientDependency
{
public ICmdHelper CmdHelper { get; }
public const string LibsDirectory = "./wwwroot/libs";
public ILogger<InstallLibsService> Logger { get; set; }
private readonly IJsonSerializer _jsonSerializer;
public InstallLibsService(IJsonSerializer jsonSerializer)
public InstallLibsService(IJsonSerializer jsonSerializer, ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
_jsonSerializer = jsonSerializer;
Logger = NullLogger<InstallLibsService>.Instance;
}

109
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/NuGet/NuGetService.cs

@ -1,3 +1,4 @@
using System;
using Newtonsoft.Json;
using NuGet.Versioning;
using System.Collections.Generic;
@ -5,7 +6,6 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Auth;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.Licensing;
using Volo.Abp.Cli.ProjectBuilding;
@ -24,7 +24,6 @@ namespace Volo.Abp.Cli.NuGet
protected IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
private readonly IApiKeyService _apiKeyService;
private readonly CliHttpClientFactory _cliHttpClientFactory;
private List<string> _proPackageList;
private DeveloperApiKeyResult _apiKeyResult;
public NuGetService(
@ -42,10 +41,32 @@ namespace Volo.Abp.Cli.NuGet
Logger = NullLogger<VoloNugetPackagesVersionUpdater>.Instance;
}
public async Task<bool> PackageExistAsync(string packageId, string version = null)
{
var versionList = await GetPackageVersionListAsync(packageId, false, true);
if (versionList == null)
{
return false;
}
if (version == null)
{
return versionList.Any();
}
return versionList.Contains(version);
}
public async Task<SemanticVersion> GetLatestVersionOrNullAsync(string packageId, bool includeNightly = false, bool includeReleaseCandidates = false)
{
var versionList = await GetPackageVersionListAsync(packageId, includeNightly, includeReleaseCandidates);
if (versionList == null)
{
return null;
}
List<SemanticVersion> versions;
if (!includeNightly && !includeReleaseCandidates)
@ -77,76 +98,54 @@ namespace Volo.Abp.Cli.NuGet
public async Task<List<string>> GetPackageVersionListAsync(string packageId, bool includeNightly = false,
bool includeReleaseCandidates = false)
{
if (AuthService.IsLoggedIn())
{
_proPackageList ??= await GetProPackageListAsync();
}
string url;
if (includeNightly)
{
url = $"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json";
}
else if (_proPackageList?.Contains(packageId) ?? false)
{
url = await GetNuGetUrlForCommercialPackage(packageId);
}
else
{
url = $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json";
var includeNightlyUrl = $"https://www.myget.org/F/abp-nightly/api/v3/flatcontainer/{packageId.ToLowerInvariant()}/index.json";
return await GetPackageVersionListFromUrlAsync(includeNightlyUrl);
}
var client = _cliHttpClientFactory.CreateClient(needsAuthentication: false);
var nugetUrl = $"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json";
var commercialUrl = await GetNuGetUrlForCommercialPackage(packageId);
using (var responseMessage = await client.GetHttpResponseMessageWithRetryAsync(
url,
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
))
{
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var responseContent = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<NuGetVersionResultDto>(responseContent).Versions;
}
return (await GetPackageVersionListFromUrlAsync(nugetUrl)) ?? (await GetPackageVersionListFromUrlAsync(commercialUrl));
}
private async Task<string> GetNuGetUrlForCommercialPackage(string packageId)
private async Task<List<string>> GetPackageVersionListFromUrlAsync(string url)
{
if (_apiKeyResult == null)
try
{
_apiKeyResult = await _apiKeyService.GetApiKeyOrNullAsync();
}
var client = _cliHttpClientFactory.CreateClient(needsAuthentication: false);
return CliUrls.GetNuGetPackageInfoUrl(_apiKeyResult.ApiKey, packageId);
using (var responseMessage = await client.GetHttpResponseMessageWithRetryAsync(
url,
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
))
{
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var responseContent = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<NuGetVersionResultDto>(responseContent).Versions;
}
}
catch (Exception)
{
return null;
}
}
private async Task<List<string>> GetProPackageListAsync()
private async Task<string> GetNuGetUrlForCommercialPackage(string packageId)
{
var url = $"{CliUrls.WwwAbpIo}api/app/nugetPackage/proPackageNames";
var client = _cliHttpClientFactory.CreateClient(needsAuthentication: true);
using (var responseMessage = await client.GetHttpResponseMessageWithRetryAsync(
url: url,
cancellationToken: CancellationTokenProvider.Token,
logger: Logger
))
if (_apiKeyResult == null)
{
if (responseMessage.IsSuccessStatusCode)
{
return JsonSerializer.Deserialize<List<string>>(await responseMessage.Content.ReadAsStringAsync());
}
var exceptionMessage = "Remote server returns '" + (int)responseMessage.StatusCode + "-" + responseMessage.ReasonPhrase + "'. ";
var remoteServiceErrorMessage = await RemoteServiceExceptionHandler.GetAbpRemoteServiceErrorAsync(responseMessage);
_apiKeyResult = await _apiKeyService.GetApiKeyOrNullAsync();
if (remoteServiceErrorMessage != null)
if (_apiKeyResult == null)
{
exceptionMessage += remoteServiceErrorMessage;
return null;
}
Logger.LogError(exceptionMessage);
return null;
}
return CliUrls.GetNuGetPackageInfoUrl(_apiKeyResult.ApiKey, packageId);
}
public class NuGetVersionResultDto
@ -155,4 +154,4 @@ namespace Volo.Abp.Cli.NuGet
public List<string> Versions { get; set; }
}
}
}
}

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectReferenceReplaceStep.cs

@ -98,11 +98,12 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
Check.NotNull(content, nameof(content));
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
using (var stream = StreamHelper.GenerateStreamFromString(content))
{
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(stream);
return ProcessReferenceNodes(doc, content);
}
}
private string ProcessReferenceNodes(XmlDocument doc, string content)

23
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -1,6 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
@ -35,6 +39,25 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var solutionFile = context.GetFile(_solutionFilePath);
solutionFile.NormalizeLineEndings();
solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList()));
RemoveProjectFromAbpmdlFile(context);
}
private void RemoveProjectFromAbpmdlFile(ProjectBuildContext context)
{
var abpmdlFile = context.FindFile(_solutionFilePath.RemovePostFix(".sln") + ".abpmdl.json");
if (abpmdlFile == null)
{
return;
}
var jsonRoot = JObject.Parse(abpmdlFile.Content);
var packagesObj = (JObject) jsonRoot["packages"];
packagesObj?.Remove(_projectName);
abpmdlFile.SetContent(jsonRoot.ToString(Formatting.Indented));
}
private List<string> RemoveProject(List<string> solutionFileLines)

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs

@ -40,11 +40,12 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
Check.NotNull(content, nameof(content));
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
using (var stream = StreamHelper.GenerateStreamFromString(content))
{
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(stream);
return ProcessReferenceNodes(doc, content);
}
}
private string ProcessReferenceNodes(XmlDocument doc, string content)

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceConfigureAwaitPropsStep.cs

@ -40,11 +40,12 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
{
Check.NotNull(content, nameof(content));
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
return ProcessReferenceNodes(doc, content);
using (var stream = StreamHelper.GenerateStreamFromString(content))
{
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(stream);
return ProcessReferenceNodes(doc, content);
}
}
private string ProcessReferenceNodes(XmlDocument doc, string content)

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs

@ -10,10 +10,12 @@ namespace Volo.Abp.Cli.ProjectModification
{
public class EfCoreMigrationManager : ITransientDependency
{
public ICmdHelper CmdHelper { get; }
public ILogger<EfCoreMigrationManager> Logger { get; set; }
public EfCoreMigrationManager()
public EfCoreMigrationManager(ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
Logger = NullLogger<EfCoreMigrationManager>.Instance;
}

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmGlobalPackagesChecker.cs

@ -7,10 +7,12 @@ namespace Volo.Abp.Cli.ProjectModification
{
public class NpmGlobalPackagesChecker : ITransientDependency
{
public ICmdHelper CmdHelper { get; }
public ILogger<NpmGlobalPackagesChecker> Logger { get; set; }
public NpmGlobalPackagesChecker()
public NpmGlobalPackagesChecker(ICmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
Logger = NullLogger<NpmGlobalPackagesChecker>.Instance;
}
@ -31,7 +33,7 @@ namespace Volo.Abp.Cli.ProjectModification
protected virtual string GetInstalledNpmPackages()
{
Logger.LogInformation("Checking installed npm global packages...");
return CmdHelper.RunCmdAndGetOutput("npm list -g --depth 0 --silent");
return CmdHelper.RunCmdAndGetOutput("npm list -g --depth 0 --silent", out int exitCode);
}
protected virtual void InstallYarn()

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs

@ -23,6 +23,7 @@ namespace Volo.Abp.Cli.ProjectModification
{
public ILogger<NpmPackagesUpdater> Logger { get; set; }
protected ICancellationTokenProvider CancellationTokenProvider { get; }
public ICmdHelper CmdHelper { get; }
private readonly PackageJsonFileFinder _packageJsonFileFinder;
private readonly NpmGlobalPackagesChecker _npmGlobalPackagesChecker;
@ -33,11 +34,13 @@ namespace Volo.Abp.Cli.ProjectModification
PackageJsonFileFinder packageJsonFileFinder,
NpmGlobalPackagesChecker npmGlobalPackagesChecker,
ICancellationTokenProvider cancellationTokenProvider,
CliHttpClientFactory cliHttpClientFactory)
CliHttpClientFactory cliHttpClientFactory,
ICmdHelper cmdHelper)
{
_packageJsonFileFinder = packageJsonFileFinder;
_npmGlobalPackagesChecker = npmGlobalPackagesChecker;
CancellationTokenProvider = cancellationTokenProvider;
CmdHelper = cmdHelper;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<NpmPackagesUpdater>.Instance;
}

14
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs

@ -31,13 +31,13 @@ namespace Volo.Abp.Cli.ProjectModification
foreach (var projectFile in projectFiles)
{
var content = File.ReadAllText(projectFile);
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
var convertedProject = ProcessReferenceNodes(folder, doc, nugetPackageList, localPathPrefix, sourceFile, modulePrefix);
File.WriteAllText(projectFile, convertedProject);
using (var stream = StreamHelper.GenerateStreamFromString(content))
{
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(stream);
var convertedProject = ProcessReferenceNodes(folder, doc, nugetPackageList, localPathPrefix, sourceFile, modulePrefix);
File.WriteAllText(projectFile, convertedProject);
}
}
}

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNpmPackageAdder.cs

@ -26,6 +26,7 @@ namespace Volo.Abp.Cli.ProjectModification
public SourceCodeDownloadService SourceCodeDownloadService { get; }
public AngularSourceCodeAdder AngularSourceCodeAdder { get; }
public IRemoteServiceExceptionHandler RemoteServiceExceptionHandler { get; }
public ICmdHelper CmdHelper { get; }
private readonly CliHttpClientFactory _cliHttpClientFactory;
public ILogger<ProjectNpmPackageAdder> Logger { get; set; }
@ -33,12 +34,14 @@ namespace Volo.Abp.Cli.ProjectModification
IJsonSerializer jsonSerializer,
SourceCodeDownloadService sourceCodeDownloadService,
AngularSourceCodeAdder angularSourceCodeAdder,
IRemoteServiceExceptionHandler remoteServiceExceptionHandler)
IRemoteServiceExceptionHandler remoteServiceExceptionHandler,
ICmdHelper cmdHelper)
{
JsonSerializer = jsonSerializer;
SourceCodeDownloadService = sourceCodeDownloadService;
AngularSourceCodeAdder = angularSourceCodeAdder;
RemoteServiceExceptionHandler = remoteServiceExceptionHandler;
CmdHelper = cmdHelper;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<ProjectNpmPackageAdder>.Instance;
}
@ -202,4 +205,4 @@ namespace Volo.Abp.Cli.ProjectModification
}
}
}
}
}

122
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs

@ -25,6 +25,7 @@ namespace Volo.Abp.Cli.ProjectModification
public BundleCommand BundleCommand { get; }
public SourceCodeDownloadService SourceCodeDownloadService { get; }
public SolutionFileModifier SolutionFileModifier { get; }
public ICmdHelper CmdHelper { get; }
protected IJsonSerializer JsonSerializer { get; }
protected ProjectNpmPackageAdder NpmPackageAdder { get; }
@ -43,7 +44,8 @@ namespace Volo.Abp.Cli.ProjectModification
BundleCommand bundleCommand,
CliHttpClientFactory cliHttpClientFactory,
SourceCodeDownloadService sourceCodeDownloadService,
SolutionFileModifier solutionFileModifier)
SolutionFileModifier solutionFileModifier,
ICmdHelper cmdHelper)
{
JsonSerializer = jsonSerializer;
NpmPackageAdder = npmPackageAdder;
@ -53,6 +55,7 @@ namespace Volo.Abp.Cli.ProjectModification
BundleCommand = bundleCommand;
SourceCodeDownloadService = sourceCodeDownloadService;
SolutionFileModifier = solutionFileModifier;
CmdHelper = cmdHelper;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<ProjectNugetPackageAdder>.Instance;
}
@ -140,37 +143,38 @@ namespace Volo.Abp.Cli.ProjectModification
return projectFile;
}
protected virtual async Task ConvertPackageReferenceToProjectReference(string projectFile,string solutionFile, NugetPackageInfo package)
protected virtual async Task ConvertPackageReferenceToProjectReference(string projectFile, string solutionFile, NugetPackageInfo package)
{
var content = File.ReadAllText(projectFile);
var doc = new XmlDocument() {PreserveWhitespace = true};
var doc = new XmlDocument() { PreserveWhitespace = true };
doc.Load(StreamHelper.GenerateStreamFromString(content));
var nodes = doc.SelectNodes(
$"/Project/ItemGroup/PackageReference[starts-with(@Include, '{package.Name}')]");
if (nodes == null || nodes.Count < 1)
using (var stream = StreamHelper.GenerateStreamFromString(content))
{
return;
}
doc.Load(stream);
var nodes = doc.SelectNodes($"/Project/ItemGroup/PackageReference[starts-with(@Include, '{package.Name}')]");
if (nodes == null || nodes.Count < 1)
{
return;
}
var downloadedProjectPath = FindRelativeFolderToDownloadPackage(projectFile, solutionFile, package);
var oldNodeIncludeValue = nodes[0]?.Attributes?["Include"]?.Value;
var downloadedProjectPath = FindRelativeFolderToDownloadPackage(projectFile, solutionFile, package);
var oldNodeIncludeValue = nodes[0]?.Attributes?["Include"]?.Value;
if (package.Name == oldNodeIncludeValue)
{
var referenceProjectPath = $"{downloadedProjectPath}\\{package.Name}.csproj";
if (package.Name == oldNodeIncludeValue)
{
var referenceProjectPath = $"{downloadedProjectPath}\\{package.Name}.csproj";
var newNode = doc.CreateElement("ProjectReference");
var includeAttr = doc.CreateAttribute("Include");
includeAttr.Value = referenceProjectPath;
newNode.Attributes.Append(includeAttr);
var newNode = doc.CreateElement("ProjectReference");
var includeAttr = doc.CreateAttribute("Include");
includeAttr.Value = referenceProjectPath;
newNode.Attributes.Append(includeAttr);
nodes[0]?.ParentNode?.ReplaceChild(newNode, nodes[0]);
}
nodes[0]?.ParentNode?.ReplaceChild(newNode, nodes[0]);
}
File.WriteAllText(projectFile, doc.OuterXml);
File.WriteAllText(projectFile, doc.OuterXml);
await Task.CompletedTask;
}
}
protected virtual async Task AddSourceCode(string projectFile, string solutionFile, NugetPackageInfo package, string version = null)
@ -192,7 +196,7 @@ namespace Volo.Abp.Cli.ProjectModification
protected virtual string FindRelativeFolderToDownloadPackage(string projectFile, string solutionFile, NugetPackageInfo package)
{
var folder = Path.Combine(Path.GetDirectoryName(solutionFile), "packages", package.Name);
var folder = Path.Combine(Path.GetDirectoryName(solutionFile), "packages", package.Name);
return new Uri(projectFile).MakeRelativeUri(new Uri(folder)).ToString().Replace("/", "\\");
}
@ -307,56 +311,52 @@ namespace Volo.Abp.Cli.ProjectModification
protected virtual Task AddToCsprojManuallyAsync(string projectFile, NugetPackageInfo package, string version = null)
{
var projectFileContent = File.ReadAllText(projectFile);
var doc = new XmlDocument() {PreserveWhitespace = true};
doc.Load(StreamHelper.GenerateStreamFromString(projectFileContent));
var itemGroupNodes = doc.SelectNodes("/Project/ItemGroup");
XmlNode itemGroupNode = null;
if (itemGroupNodes == null || itemGroupNodes.Count < 1)
var doc = new XmlDocument() { PreserveWhitespace = true };
using (var stream = StreamHelper.GenerateStreamFromString(projectFileContent))
{
var projectNodes = doc.SelectNodes("/Project");
var projectNode = projectNodes[0];
doc.Load(stream);
itemGroupNode = doc.CreateElement("ItemGroup");
projectNode.AppendChild(itemGroupNode);
}
else
{
itemGroupNode = itemGroupNodes[0];
}
var itemGroupNodes = doc.SelectNodes("/Project/ItemGroup");
XmlNode itemGroupNode = null;
var packageReferenceNode = doc.CreateElement("PackageReference");
if (itemGroupNodes == null || itemGroupNodes.Count < 1)
{
var projectNodes = doc.SelectNodes("/Project");
var projectNode = projectNodes[0];
var includeAttr = doc.CreateAttribute("Include");
includeAttr.Value = package.Name;
packageReferenceNode.Attributes.Append(includeAttr);
itemGroupNode = doc.CreateElement("ItemGroup");
projectNode.AppendChild(itemGroupNode);
}
else
{
itemGroupNode = itemGroupNodes[0];
}
if (version != null)
{
var versionAttr = doc.CreateAttribute("Version");
versionAttr.Value = version;
packageReferenceNode.Attributes.Append(versionAttr);
}
var packageReferenceNode = doc.CreateElement("PackageReference");
itemGroupNode.AppendChild(packageReferenceNode);
var includeAttr = doc.CreateAttribute("Include");
includeAttr.Value = package.Name;
packageReferenceNode.Attributes.Append(includeAttr);
File.WriteAllText(projectFile, doc.OuterXml);
if (version != null)
{
var versionAttr = doc.CreateAttribute("Version");
versionAttr.Value = version;
packageReferenceNode.Attributes.Append(versionAttr);
}
return Task.CompletedTask;
itemGroupNode.AppendChild(packageReferenceNode);
File.WriteAllText(projectFile, doc.OuterXml);
return Task.CompletedTask;
}
}
protected virtual string GetAbpVersionOrNull(string projectFile)
{
var projectFileContent = File.ReadAllText(projectFile);
var doc = new XmlDocument() {PreserveWhitespace = true};
doc.Load(StreamHelper.GenerateStreamFromString(projectFileContent));
var nodes = doc.SelectNodes("/Project/ItemGroup/PackageReference[starts-with(@Include, 'Volo.')]");
return nodes?[0]?.Attributes?["Version"]?.Value;
return SolutionPackageVersionFinder.TryParseVersionFromCsprojFile(projectFileContent, out var version)
? version
: null;
}
protected virtual async Task<NugetPackageInfo> FindNugetPackageInfoAsync(string packageName)

7
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

@ -30,6 +30,7 @@ namespace Volo.Abp.Cli.ProjectModification
public AngularSourceCodeAdder AngularSourceCodeAdder { get; }
public NewCommand NewCommand { get; }
public BundleCommand BundleCommand { get; }
public ICmdHelper CmdHelper { get; }
protected IJsonSerializer JsonSerializer { get; }
protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; }
@ -58,7 +59,8 @@ namespace Volo.Abp.Cli.ProjectModification
AngularSourceCodeAdder angularSourceCodeAdder,
NewCommand newCommand,
BundleCommand bundleCommand,
CliHttpClientFactory cliHttpClientFactory)
CliHttpClientFactory cliHttpClientFactory,
ICmdHelper cmdHelper)
{
JsonSerializer = jsonSerializer;
ProjectNugetPackageAdder = projectNugetPackageAdder;
@ -74,6 +76,7 @@ namespace Volo.Abp.Cli.ProjectModification
AngularSourceCodeAdder = angularSourceCodeAdder;
NewCommand = newCommand;
BundleCommand = bundleCommand;
CmdHelper = cmdHelper;
_cliHttpClientFactory = cliHttpClientFactory;
Logger = NullLogger<SolutionModuleAdder>.Instance;
}
@ -620,7 +623,7 @@ namespace Volo.Abp.Cli.ProjectModification
if (!string.IsNullOrEmpty(dbMigratorProject))
{
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProject) + "\" && dotnet run");
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(dbMigratorProject) + "\" && dotnet run", out int exitCode);
}
}

26
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionAbpVersionFinder.cs → framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionPackageVersionFinder.cs

@ -7,15 +7,15 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification
{
public class SolutionAbpVersionFinder : ITransientDependency
public class SolutionPackageVersionFinder : ITransientDependency
{
public string Find(string solutionFile)
public string Find(string solutionFile, string packagePrefix = "Volo.Abp")
{
var projectFilesUnderSrc = GetProjectFilesOfSolution(solutionFile);
foreach (var projectFile in projectFilesUnderSrc)
{
var content = File.ReadAllText(projectFile);
if (TryParseVersionFromCsprojViaXmlDocument(content, out var s))
if (TryParseVersionFromCsprojViaXmlDocument(content, out var s, packagePrefix))
{
return s;
}
@ -24,13 +24,13 @@ namespace Volo.Abp.Cli.ProjectModification
return null;
}
private static bool TryParseVersionFromCsprojViaXmlDocument(string content, out string version)
private static bool TryParseVersionFromCsprojViaXmlDocument(string content, out string version, string packagePrefix)
{
var doc = new XmlDocument() { PreserveWhitespace = true };
using (var stream = StreamHelper.GenerateStreamFromString(content))
{
doc.Load(stream);
var nodes = doc.SelectNodes("/Project/ItemGroup/PackageReference[starts-with(@Include, 'Volo.Abp')]");
var nodes = doc.SelectNodes($"/Project/ItemGroup/PackageReference[starts-with(@Include, '{packagePrefix}')]");
var value = nodes?[0]?.Attributes?["Version"]?.Value;
if (value == null)
{
@ -43,12 +43,12 @@ namespace Volo.Abp.Cli.ProjectModification
}
}
public static bool TryParseVersionFromCsprojFile(string csprojContent, out string version)
public static bool TryParseVersionFromCsprojFile(string csprojContent, out string version, string packagePrefix = "Volo.Abp")
{
try
{
var matches = Regex.Matches(csprojContent,
@"PackageReference\s*Include\s*=\s*\""Volo.Abp(.*?)\""\s*Version\s*=\s*\""(.*?)\""",
@"PackageReference\s*Include\s*=\s*\""" + packagePrefix + @"(.*?)\""\s*Version\s*=\s*\""(.*?)\""",
RegexOptions.IgnoreCase |
RegexOptions.IgnorePatternWhitespace |
RegexOptions.Singleline | RegexOptions.Multiline);
@ -72,11 +72,11 @@ namespace Volo.Abp.Cli.ProjectModification
}
public static bool TryParseSemanticVersionFromCsprojFile(string csprojContent, out SemanticVersion version)
public static bool TryParseSemanticVersionFromCsprojFile(string csprojContent, out SemanticVersion version, string packagePrefix = "Volo.Abp")
{
try
{
if (TryParseVersionFromCsprojFile(csprojContent, out var versionText))
if (TryParseVersionFromCsprojFile(csprojContent, out var versionText, packagePrefix))
{
return SemanticVersion.TryParse(versionText, out version);
}
@ -90,13 +90,13 @@ namespace Volo.Abp.Cli.ProjectModification
return false;
}
public static bool TryFind(string solutionFile, out string version)
public static bool TryFind(string solutionFile, out string version, string packagePrefix = "Volo.Abp")
{
var projectFiles = GetProjectFilesOfSolution(solutionFile);
foreach (var projectFile in projectFiles)
{
var csprojContent = File.ReadAllText(projectFile);
if (TryParseVersionFromCsprojFile(csprojContent, out var parsedVersion))
if (TryParseVersionFromCsprojFile(csprojContent, out var parsedVersion, packagePrefix))
{
version = parsedVersion;
return true;
@ -107,13 +107,13 @@ namespace Volo.Abp.Cli.ProjectModification
return false;
}
public static bool TryFindSemanticVersion(string solutionFile, out SemanticVersion version)
public static bool TryFindSemanticVersion(string solutionFile, out SemanticVersion version, string packagePrefix = "Volo.Abp")
{
var projectFiles = GetProjectFilesOfSolution(solutionFile);
foreach (var projectFile in projectFiles)
{
var csprojContent = File.ReadAllText(projectFile);
if (TryParseSemanticVersionFromCsprojFile(csprojContent, out var parsedVersion))
if (TryParseSemanticVersionFromCsprojFile(csprojContent, out var parsedVersion, packagePrefix))
{
version = parsedVersion;
return true;

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/Angular/AngularServiceProxyGenerator.cs

@ -17,13 +17,16 @@ namespace Volo.Abp.Cli.ServiceProxying.Angular
public const string Name = "NG";
private readonly CliService _cliService;
private readonly ICmdHelper _cmdhelper;
public AngularServiceProxyGenerator(
CliHttpClientFactory cliHttpClientFactory,
IJsonSerializer jsonSerializer,
ICmdHelper cmdhelper,
CliService cliService) :
base(cliHttpClientFactory, jsonSerializer)
{
_cmdhelper = cmdhelper;
_cliService = cliService;
}
@ -63,7 +66,7 @@ namespace Volo.Abp.Cli.ServiceProxying.Angular
commandBuilder.Append($" --target {target}");
}
CmdHelper.RunCmd(commandBuilder.ToString());
_cmdhelper.RunCmd(commandBuilder.ToString());
}
private async Task CheckNgSchematicsAsync()

46
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/CmdHelper.cs

@ -1,14 +1,15 @@
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Utils
{
public static class CmdHelper
public class CmdHelper : ICmdHelper, ITransientDependency
{
public static int SuccessfulExitCode = 0;
private const int SuccessfulExitCode = 0;
public static void OpenWebPage(string url)
public void OpenWebPage(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
@ -25,45 +26,57 @@ namespace Volo.Abp.Cli.Utils
}
}
public static void Run(string file, string arguments)
public void Run(string file, string arguments)
{
var procStartInfo = new ProcessStartInfo(file, arguments);
Process.Start(procStartInfo)?.WaitForExit();
}
public static int RunCmd(string command)
public void RunCmd(string command, string workingDirectory = null)
{
RunCmd(command, out _, workingDirectory);
}
public void RunCmd(string command, out int exitCode, string workingDirectory = null)
{
var procStartInfo = new ProcessStartInfo(
GetFileName(),
GetArguments(command)
);
if (!string.IsNullOrEmpty(workingDirectory))
{
procStartInfo.WorkingDirectory = workingDirectory;
}
using (var process = Process.Start(procStartInfo))
{
process?.WaitForExit();
return process?.ExitCode ?? 0;
exitCode = process.ExitCode;
}
}
public static string RunCmdAndGetOutput(string command)
public string RunCmdAndGetOutput(string command, string workingDirectory = null)
{
return RunCmdAndGetOutput(command, out int _);
return RunCmdAndGetOutput(command, out int _, workingDirectory);
}
public static string RunCmdAndGetOutput(string command, out bool isExitCodeSuccessful)
public string RunCmdAndGetOutput(string command, out bool isExitCodeSuccessful, string workingDirectory = null)
{
var output = RunCmdAndGetOutput(command, out int exitCode);
var output = RunCmdAndGetOutput(command, out int exitCode, workingDirectory);
isExitCodeSuccessful = exitCode == SuccessfulExitCode;
return output;
}
public static string RunCmdAndGetOutput(string command, out int exitCode)
public string RunCmdAndGetOutput(string command, out int exitCode, string workingDirectory = null)
{
string output;
using (var process = new Process())
{
process.StartInfo = new ProcessStartInfo(CmdHelper.GetFileName())
process.StartInfo = new ProcessStartInfo(GetFileName())
{
Arguments = GetArguments(command),
UseShellExecute = false,
@ -72,6 +85,11 @@ namespace Volo.Abp.Cli.Utils
RedirectStandardError = true
};
if (!string.IsNullOrEmpty(workingDirectory))
{
process.StartInfo.WorkingDirectory = workingDirectory;
}
process.Start();
using (var standardOutput = process.StandardOutput)
@ -91,7 +109,7 @@ namespace Volo.Abp.Cli.Utils
return output.Trim();
}
public static string GetArguments(string command)
public string GetArguments(string command)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
@ -102,7 +120,7 @@ namespace Volo.Abp.Cli.Utils
return "/C \"" + command + "\"";
}
public static string GetFileName()
public string GetFileName()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{

24
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ICmdHelper.cs

@ -0,0 +1,24 @@
namespace Volo.Abp.Cli.Utils
{
public interface ICmdHelper
{
void OpenWebPage(string url);
void Run(string file, string arguments);
string GetArguments(string command);
string GetFileName();
void RunCmd(string command, string workingDirectory = null);
void RunCmd(string command, out int exitCode, string workingDirectory = null);
string RunCmdAndGetOutput(string command, string workingDirectory = null);
string RunCmdAndGetOutput(string command, out bool isExitCodeSuccessful, string workingDirectory = null);
string RunCmdAndGetOutput(string command, out int exitCode, string workingDirectory = null);
}
}

100
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Reflection;
@ -50,5 +51,102 @@ namespace Volo.Abp.DependencyInjection
}
}
}
protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type)
{
return type.GetCustomAttribute<DependencyAttribute>(true);
}
protected virtual ServiceLifetime? GetLifeTimeOrNull(Type type, [CanBeNull] DependencyAttribute dependencyAttribute)
{
return dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromClassHierarchy(type) ?? GetDefaultLifeTimeOrNull(type);
}
protected virtual ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type)
{
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Transient;
}
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Singleton;
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Scoped;
}
return null;
}
protected virtual ServiceLifetime? GetDefaultLifeTimeOrNull(Type type)
{
return null;
}
protected virtual List<Type> GetExposedServiceTypes(Type type)
{
return ExposedServiceExplorer.GetExposedServices(type);
}
protected virtual ServiceDescriptor CreateServiceDescriptor(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes,
ServiceLifetime lifeTime)
{
if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped))
{
var redirectedType = GetRedirectedTypeOrNull(
implementationType,
exposingServiceType,
allExposingServiceTypes
);
if (redirectedType != null)
{
return ServiceDescriptor.Describe(
exposingServiceType,
provider => provider.GetService(redirectedType),
lifeTime
);
}
}
return ServiceDescriptor.Describe(
exposingServiceType,
implementationType,
lifeTime
);
}
protected virtual Type GetRedirectedTypeOrNull(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes)
{
if (allExposingServiceTypes.Count < 2)
{
return null;
}
if (exposingServiceType == implementationType)
{
return null;
}
if (allExposingServiceTypes.Contains(implementationType))
{
return implementationType;
}
return allExposingServiceTypes.FirstOrDefault(
t => t != exposingServiceType && exposingServiceType.IsAssignableFrom(t)
);
}
}
}
}

95
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -53,96 +49,5 @@ namespace Volo.Abp.DependencyInjection
}
}
}
protected virtual List<Type> GetExposedServiceTypes(Type type)
{
return ExposedServiceExplorer.GetExposedServices(type);
}
protected virtual ServiceDescriptor CreateServiceDescriptor(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes,
ServiceLifetime lifeTime)
{
if (lifeTime.IsIn(ServiceLifetime.Singleton, ServiceLifetime.Scoped))
{
var redirectedType = GetRedirectedTypeOrNull(
implementationType,
exposingServiceType,
allExposingServiceTypes
);
if (redirectedType != null)
{
return ServiceDescriptor.Describe(
exposingServiceType,
provider => provider.GetService(redirectedType),
lifeTime
);
}
}
return ServiceDescriptor.Describe(
exposingServiceType,
implementationType,
lifeTime
);
}
protected virtual Type GetRedirectedTypeOrNull(
Type implementationType,
Type exposingServiceType,
List<Type> allExposingServiceTypes)
{
if (allExposingServiceTypes.Count < 2)
{
return null;
}
if (exposingServiceType == implementationType)
{
return null;
}
if (allExposingServiceTypes.Contains(implementationType))
{
return implementationType;
}
return allExposingServiceTypes.FirstOrDefault(
t => t != exposingServiceType && exposingServiceType.IsAssignableFrom(t)
);
}
protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type)
{
return type.GetCustomAttribute<DependencyAttribute>(true);
}
protected virtual ServiceLifetime? GetLifeTimeOrNull(Type type, [CanBeNull] DependencyAttribute dependencyAttribute)
{
return dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromClassHierarchy(type);
}
protected virtual ServiceLifetime? GetServiceLifetimeFromClassHierarchy(Type type)
{
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Transient;
}
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Singleton;
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Scoped;
}
return null;
}
}
}

2
framework/src/Volo.Abp.Ddd.Domain/Volo.Abp.Ddd.Domain.csproj

@ -17,7 +17,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus.Boxes\Volo.Abp.EventBus.Boxes.csproj" />
<ProjectReference Include="..\Volo.Abp.EventBus\Volo.Abp.EventBus.csproj" />
<ProjectReference Include="..\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj" />
<ProjectReference Include="..\Volo.Abp.Guids\Volo.Abp.Guids.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save