mirror of https://github.com/abpframework/abp
Merge pull request #8567 from abpframework/auto-merge/rel-4-3/288
Merge branch dev with rel-4.3pull/8371/head^2
commit
12c6405b9d
@ -0,0 +1,71 @@
|
|||||||
|
# Cancellation Token Provider
|
||||||
|
|
||||||
|
A `CancellationToken` enables cooperative cancellation between threads, thread pool work items, or `Task` objects. To handle the possible cancellation of the operation, ABP Framework provides `ICancellationTokenProvider` to obtain the `CancellationToken` itself from the source.
|
||||||
|
|
||||||
|
> To get more information about `CancellationToken`, see [Microsoft Documentation](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken).
|
||||||
|
|
||||||
|
## ICancellationTokenProvider
|
||||||
|
|
||||||
|
`ICancellationTokenProvider` is an abstraction to provide `CancellationToken` for different scenarios.
|
||||||
|
|
||||||
|
Generally, you should pass the `CancellationToken` as a parameter for your method to use it. With the `ICancellationTokenProvider` you don't need to pass `CancellationToken` for every method. `ICancellationTokenProvider` can be injected with the **dependency injection** and provides the token from it's source.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Threading;
|
||||||
|
|
||||||
|
namespace MyProject
|
||||||
|
{
|
||||||
|
public class MyService : ITransientDependency
|
||||||
|
{
|
||||||
|
private readonly ICancellationTokenProvider _cancellationTokenProvider;
|
||||||
|
|
||||||
|
public MyService(ICancellationTokenProvider cancellationTokenProvider)
|
||||||
|
{
|
||||||
|
_cancellationTokenProvider = cancellationTokenProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DoItAsync()
|
||||||
|
{
|
||||||
|
while (_cancellationTokenProvider.Token.IsCancellationRequested == false)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Built-in providers
|
||||||
|
|
||||||
|
- `NullCancellationTokenProvider`
|
||||||
|
|
||||||
|
The `NullCancellationTokenProvider` is a built in provider and it supply always `CancellationToken.None`.
|
||||||
|
|
||||||
|
- `HttpContextCancellationTokenProvider`
|
||||||
|
|
||||||
|
The `HttpContextCancellationTokenProvider` is a built in default provider for ABP Web applications. It simply provides a `CancellationToken` that is source of the web request from the `HttpContext`.
|
||||||
|
|
||||||
|
## Implementing the ICancellationTokenProvider
|
||||||
|
|
||||||
|
You can easily create your CancellationTokenProvider by creating a class that implements the `ICancellationTokenProvider` interface, as shown below:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace AbpDemo
|
||||||
|
{
|
||||||
|
public class MyCancellationTokenProvider : ICancellationTokenProvider
|
||||||
|
{
|
||||||
|
public CancellationToken Token { get; }
|
||||||
|
|
||||||
|
private MyCancellationTokenProvider()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -1,3 +1,117 @@
|
|||||||
# Global Features
|
# Global Features
|
||||||
|
The purpose of the Global Feature System is to **add a module to your application but disable the features you don't want to use** (or enable only the ones you need). Notice that the features are not determined on runtime, you must select the features **on development time**. Because it will not create database tables, APIs and other stuff for unused features, which is not possible to change then on the runtime.
|
||||||
|
|
||||||
TODO (see [#5061](https://github.com/abpframework/abp/issues/5061) until this is documented).
|
## Installation
|
||||||
|
> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
|
||||||
|
|
||||||
|
### 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.GlobalFeatures
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
Global Feature system aims module based feature management . A module has to have own Global Features itself.
|
||||||
|
|
||||||
|
### Define a Global Feature
|
||||||
|
|
||||||
|
A feature class is something like that:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[GlobalFeatureName(Name)]
|
||||||
|
public class PaymentFeature : GlobalFeature
|
||||||
|
{
|
||||||
|
public const string Name = "Shopping.Payment";
|
||||||
|
|
||||||
|
public PaymentFeature(GlobalModuleFeatures module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Define Global Module Features
|
||||||
|
|
||||||
|
All features of a module have to be defined in a Global Module Features class.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class GlobalShoppingFeatures : GlobalModuleFeatures
|
||||||
|
{
|
||||||
|
public const string ModuleName = "Shopping";
|
||||||
|
|
||||||
|
public GlobalShoppingFeatures(GlobalFeatureManager featureManager) : base(featureManager)
|
||||||
|
{
|
||||||
|
AddFeature(new PaymentFeature(this));
|
||||||
|
// And more features...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Enable/Disable Features
|
||||||
|
|
||||||
|
Global features are managed by modules. Module Features have to be added to Modules of GlobalFeatureManager.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// GerOrAdd might be useful to be sure module features are added.
|
||||||
|
var shoppingGlobalFeatures = GlobalFeatureManager.Instance.Modules
|
||||||
|
.GetOrAdd(
|
||||||
|
GlobalShoppingFeatures.ModuleName,
|
||||||
|
()=> new GlobalShoppingFeatures(GlobalFeatureManager.Instance));
|
||||||
|
|
||||||
|
// Able to Enable/Disable with generic type parameter.
|
||||||
|
shoppingGlobalFeatures.Enable<PaymentFeature>();
|
||||||
|
shoppingGlobalFeatures.Disable<PaymentFeature>();
|
||||||
|
|
||||||
|
// Also able to Enable/Disable with string feature name.
|
||||||
|
shoppingGlobalFeatures.Enable(PaymentFeature.Name);
|
||||||
|
shoppingGlobalFeatures.Disable("Shopping.Payment");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check if a feature is enabled
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
GlobalFeatureManager.Instance.IsEnabled<PaymentFeature>()
|
||||||
|
GlobalFeatureManager.Instance.IsEnabled("Shopping.Payment")
|
||||||
|
```
|
||||||
|
|
||||||
|
Both methods return `bool`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
if (GlobalFeatureManager.Instance.IsEnabled<PaymentFeature>())
|
||||||
|
{
|
||||||
|
// Some strong payment codes here...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Beside the manual check, there is `[RequiresGlobalFeature]` attribute to check it declaratively for a controller or page. ABP returns 404 if the related feature was disabled.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[RequiresGlobalFeature(typeof(CommentsFeature))]
|
||||||
|
public class PaymentController : AbpController
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to configure Global Features?
|
||||||
|
Global Features have to be configured before application startup. So best place to configuring it is `PreConfigureServices` with **OneTimeRunner** to make sure it runs one time.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
|
||||||
|
public override void PreConfigureServices(ServiceConfigurationContext context)
|
||||||
|
{
|
||||||
|
OneTimeRunner.Run(() =>
|
||||||
|
{
|
||||||
|
GlobalFeatureManager.Instance.Modules.Foo().EnableAll();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features vs Global Features
|
||||||
|
[Features](Features.md) & [Global Features](Global-Features.md) are totally different systems.
|
||||||
|
|
||||||
|
Features are used to switch on/off application feature for each tenant. So Features, only hides disabled ones, but with Global Features, disabled features pretends like never existed in application.
|
Loading…
Reference in new issue