Browse Source

Merge pull request #11192 from abpframework/auto-merge/rel-5-0/766

Merge branch dev with rel-5.0
pull/11197/head
maliming 5 years ago
committed by GitHub
parent
commit
ed34dc931c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      docs/en/Background-Workers-Hangfire.md
  2. 9
      docs/en/Modules/Cms-Kit/Index.md
  3. 30
      docs/zh-Hans/Background-Workers-Hangfire.md
  4. 9
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs
  5. 5
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs
  6. 9
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzPeriodicBackgroundWorkerAdapter.cs
  7. 20
      framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/ProxyHelper.cs
  8. 48
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs
  9. 33
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ListResultDto.cs
  10. 9
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedAndSortedResultRequestDto.cs
  11. 30
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedResultDto.cs
  12. 12
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedResultRequestDto.cs
  13. 2
      templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebTestModule.cs

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

@ -66,6 +66,33 @@ public class MyLogWorker : HangfireBackgroundWorkerBase
> You can directly implement the `IHangfireBackgroundWorker`, but `HangfireBackgroundWorkerBase` provides some useful properties like Logger.
### UnitOfWork
For use with `UnitOfWorkAttribute`, you need to define an interface for worker:
```csharp
public interface IMyLogWorker : IHangfireBackgroundWorker
{
}
[ExposeServices(typeof(IMyLogWorker))]
public class MyLogWorker : HangfireBackgroundWorkerBase, IMyLogWorker
{
public MyLogWorker()
{
RecurringJobId = nameof(MyLogWorker);
CronExpression = Cron.Daily();
}
[UnitOfWork]
public override Task DoWorkAsync()
{
Logger.LogInformation("Executed MyLogWorker..!");
return Task.CompletedTask;
}
}
```
## 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:
@ -78,6 +105,9 @@ public class MyModule : AbpModule
ApplicationInitializationContext context)
{
context.AddBackgroundWorker<MyLogWorker>();
//If the interface is defined
//context.AddBackgroundWorker<IMyLogWorker>();
}
}
````

9
docs/en/Modules/Cms-Kit/Index.md

@ -19,15 +19,14 @@ Click to a feature to understand and learn how to use it.
All features are individually usable. If you disable a feature, it completely disappears from your application, even from the database tables, by the help of the [Global Features](../../Global-Features.md) system.
## Pre Requirements
- This module depends on [BlobStoring](../../Blob-Storing.md) module for keeping media content.
> Make sure `BlobStoring` module is installed and at leats one provider is configured properly. For more information, check the [documentation](../../Blob-Storing.md).
CMS Kit uses [distributed cache](../../Caching.md) for responding faster.
- CMS Kit uses [distributed cache](../../Caching.md) for responding faster.
> Using a distributed cache, such as [Redis](../../Redis-Cache.md), is highly recommended for data consistency in distributed/clustered deployments.
## How to Install
> This module is depends on [BlobStoring](../../Blob-Storing.md) module, please install `BlobStoring` module first and add a provider. For more information, check the [documentation](../../Blob-Storing.md).
[ABP CLI](../../CLI.md) allows installing a module to a solution using the `add-module` command. You can install the CMS Kit module in a command-line terminal with the following command:
```bash
@ -77,4 +76,4 @@ All tables/collections use the `Cms` prefix by default. Set static properties on
This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string.
See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details.
See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details.

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

@ -67,6 +67,33 @@ public class MyLogWorker : HangfireBackgroundWorkerBase
> 你可以直接实现 `IHangfireBackgroundWorker`, 但是 `HangfireBackgroundWorkerBase` 提供了一些有用的属性,例如 `Logger`.
### UnitOfWork
使用 `UnitOfWorkAttribute` 你需要为工作者定义一个接口:
```csharp
public interface IMyLogWorker : IHangfireBackgroundWorker
{
}
[ExposeServices(typeof(IMyLogWorker))]
public class MyLogWorker : HangfireBackgroundWorkerBase, IMyLogWorker
{
public MyLogWorker()
{
RecurringJobId = nameof(MyLogWorker);
CronExpression = Cron.Daily();
}
[UnitOfWork]
public override Task DoWorkAsync()
{
Logger.LogInformation("Executed MyLogWorker..!");
return Task.CompletedTask;
}
}
```
## 注册到后台工作者管理器
创建一个后台工作者后, 你应该添加到 `IBackgroundWorkerManager`, 最常用的地方是在你模块类的 `OnApplicationInitialization` 方法中:
@ -79,6 +106,9 @@ public class MyModule : AbpModule
ApplicationInitializationContext context)
{
context.AddBackgroundWorker<MyLogWorker>();
//如果定义了接口
//context.AddBackgroundWorker<IMyLogWorker>();
}
}
````

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

@ -4,6 +4,7 @@ using System.Threading;
using System.Threading.Tasks;
using Hangfire;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers.Hangfire;
@ -25,14 +26,14 @@ public class HangfireBackgroundWorkerManager : IBackgroundWorkerManager, ISingle
{
if (worker is IHangfireBackgroundWorker hangfireBackgroundWorker)
{
var unProxyWorker = ProxyHelper.UnProxy(hangfireBackgroundWorker);
if (hangfireBackgroundWorker.RecurringJobId.IsNullOrWhiteSpace())
{
RecurringJob.AddOrUpdate(() => hangfireBackgroundWorker.DoWorkAsync(),
hangfireBackgroundWorker.CronExpression);
RecurringJob.AddOrUpdate(() => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(),hangfireBackgroundWorker.CronExpression);
}
else
{
RecurringJob.AddOrUpdate(hangfireBackgroundWorker.RecurringJobId,() => hangfireBackgroundWorker.DoWorkAsync(),
RecurringJob.AddOrUpdate(hangfireBackgroundWorker.RecurringJobId,() => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(),
hangfireBackgroundWorker.CronExpression);
}
}
@ -64,7 +65,7 @@ public class HangfireBackgroundWorkerManager : IBackgroundWorkerManager, ISingle
return Task.CompletedTask;
}
var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(worker.GetType());
var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(ProxyHelper.GetUnProxiedType(worker));
var workerAdapter = Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker;
RecurringJob.AddOrUpdate(() => workerAdapter.DoWorkAsync(), GetCron(period.Value));

5
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs

@ -1,8 +1,9 @@
using System;
using System;
using System.Threading;
using System.Threading.Tasks;
using Quartz;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers.Quartz;
@ -56,7 +57,7 @@ public class QuartzBackgroundWorkerManager : IBackgroundWorkerManager, ISingleto
}
else
{
var adapterType = typeof(QuartzPeriodicBackgroundWorkerAdapter<>).MakeGenericType(worker.GetType());
var adapterType = typeof(QuartzPeriodicBackgroundWorkerAdapter<>).MakeGenericType(ProxyHelper.GetUnProxiedType(worker));
var workerAdapter = Activator.CreateInstance(adapterType) as IQuartzBackgroundWorkerAdapter;

9
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzPeriodicBackgroundWorkerAdapter.cs

@ -1,7 +1,8 @@
using System;
using System;
using System.Reflection;
using System.Threading.Tasks;
using Quartz;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers.Quartz;
@ -26,16 +27,16 @@ public class QuartzPeriodicBackgroundWorkerAdapter<TWorker> : QuartzBackgroundWo
public void BuildWorker(IBackgroundWorker worker)
{
int? period;
var workerType = worker.GetType();
var workerType = ProxyHelper.GetUnProxiedType(worker);
if (worker is AsyncPeriodicBackgroundWorkerBase or PeriodicBackgroundWorkerBase)
{
if (typeof(TWorker) != worker.GetType())
if (typeof(TWorker) != workerType)
{
throw new ArgumentException($"{nameof(worker)} type is different from the generic type");
}
var timer = worker.GetType().GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker);
var timer = workerType.GetProperty("Timer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(worker);
if (worker is AsyncPeriodicBackgroundWorkerBase)
{

20
framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/ProxyHelper.cs

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Reflection;
@ -9,7 +9,7 @@ public static class ProxyHelper
private const string ProxyNamespace = "Castle.Proxies";
/// <summary>
/// Returns dynamic proxy target object if this is a proxied object, otherwise returns the given object.
/// Returns dynamic proxy target object if this is a proxied object, otherwise returns the given object.
/// It supports Castle Dynamic Proxies.
/// </summary>
public static object UnProxy(object obj)
@ -33,6 +33,20 @@ public static class ProxyHelper
public static Type GetUnProxiedType(object obj)
{
return UnProxy(obj).GetType();
if (obj.GetType().Namespace == ProxyNamespace)
{
var target = UnProxy(obj);
if (target != null)
{
if (target == obj)
{
return obj.GetType().GetTypeInfo().BaseType;
}
return target.GetType();
}
}
return obj.GetType();
}
}

48
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/LimitedResultRequestDto.cs

@ -49,3 +49,51 @@ public class LimitedResultRequestDto : ILimitedResultRequest, IValidatableObject
}
}
}
/// <summary>
/// Simply implements <see cref="ILimitedResultRequest"/>.
/// </summary>
[Serializable]
public class ExtensibleLimitedResultRequestDto : ExtensibleEntityDto, ILimitedResultRequest, IValidatableObject
{
/// <summary>
/// Default value: 10.
/// </summary>
public static int DefaultMaxResultCount { get; set; } = 10;
/// <summary>
/// Maximum possible value of the <see cref="MaxResultCount"/>.
/// Default value: 1,000.
/// </summary>
public static int MaxMaxResultCount { get; set; } = 1000;
/// <summary>
/// Maximum result count should be returned.
/// This is generally used to limit result count on paging.
/// </summary>
[Range(1, int.MaxValue)]
public virtual int MaxResultCount { get; set; } = DefaultMaxResultCount;
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
foreach(var result in base.Validate(validationContext))
{
yield return result;
}
if (MaxResultCount > MaxMaxResultCount)
{
var localizer = validationContext.GetRequiredService<IStringLocalizer<AbpDddApplicationContractsResource>>();
yield return new ValidationResult(
localizer[
"MaxResultCountExceededExceptionMessage",
nameof(MaxResultCount),
MaxMaxResultCount,
typeof(ExtensibleLimitedResultRequestDto).FullName,
nameof(MaxMaxResultCount)
],
new[] { nameof(MaxResultCount) });
}
}
}

33
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/ListResultDto.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Volo.Abp.ObjectExtending;
namespace Volo.Abp.Application.Dtos;
@ -7,7 +8,8 @@ namespace Volo.Abp.Application.Dtos;
public class ListResultDto<T> : IListResult<T>
{
/// <inheritdoc />
public IReadOnlyList<T> Items {
public IReadOnlyList<T> Items
{
get { return _items ?? (_items = new List<T>()); }
set { _items = value; }
}
@ -30,3 +32,32 @@ public class ListResultDto<T> : IListResult<T>
Items = items;
}
}
[Serializable]
public class ExtensibleListResultDto<T> : ExtensibleObject, IListResult<T>
{
/// <inheritdoc />
public IReadOnlyList<T> Items
{
get { return _items ?? (_items = new List<T>()); }
set { _items = value; }
}
private IReadOnlyList<T> _items;
/// <summary>
/// Creates a new <see cref="ListResultDto{T}"/> object.
/// </summary>
public ExtensibleListResultDto()
{
}
/// <summary>
/// Creates a new <see cref="ListResultDto{T}"/> object.
/// </summary>
/// <param name="items">List of items</param>
public ExtensibleListResultDto(IReadOnlyList<T> items)
{
Items = items;
}
}

9
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedAndSortedResultRequestDto.cs

@ -10,3 +10,12 @@ public class PagedAndSortedResultRequestDto : PagedResultRequestDto, IPagedAndSo
{
public virtual string Sorting { get; set; }
}
/// <summary>
/// Simply implements <see cref="IPagedAndSortedResultRequest"/>.
/// </summary>
[Serializable]
public class ExtensiblePagedAndSortedResultRequestDto : ExtensiblePagedResultRequestDto, IPagedAndSortedResultRequest
{
public virtual string Sorting { get; set; }
}

30
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedResultDto.cs

@ -32,3 +32,33 @@ public class PagedResultDto<T> : ListResultDto<T>, IPagedResult<T>
TotalCount = totalCount;
}
}
/// <summary>
/// Implements <see cref="IPagedResult{T}"/>.
/// </summary>
/// <typeparam name="T">Type of the items in the <see cref="ListResultDto{T}.Items"/> list</typeparam>
[Serializable]
public class ExtensiblePagedResultDto<T> : ExtensibleListResultDto<T>, IPagedResult<T>
{
/// <inheritdoc />
public long TotalCount { get; set; } //TODO: Can be a long value..?
/// <summary>
/// Creates a new <see cref="PagedResultDto{T}"/> object.
/// </summary>
public ExtensiblePagedResultDto()
{
}
/// <summary>
/// Creates a new <see cref="PagedResultDto{T}"/> object.
/// </summary>
/// <param name="totalCount">Total count of Items</param>
/// <param name="items">List of items in current page</param>
public ExtensiblePagedResultDto(long totalCount, IReadOnlyList<T> items)
: base(items)
{
TotalCount = totalCount;
}
}

12
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Dtos/PagedResultRequestDto.cs

@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.Application.Dtos;
@ -12,3 +12,13 @@ public class PagedResultRequestDto : LimitedResultRequestDto, IPagedResultReques
[Range(0, int.MaxValue)]
public virtual int SkipCount { get; set; }
}
/// <summary>
/// Simply implements <see cref="IPagedResultRequest"/>.
/// </summary>
[Serializable]
public class ExtensiblePagedResultRequestDto : ExtensibleLimitedResultRequestDto, IPagedResultRequest
{
[Range(0, int.MaxValue)]
public virtual int SkipCount { get; set; }
}

2
templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyProjectNameWebTestModule.cs

@ -27,7 +27,7 @@ public class MyProjectNameWebTestModule : AbpModule
{
context.Services.PreConfigure<IMvcBuilder>(builder =>
{
builder.PartManager.ApplicationParts.Add(new AssemblyPart(typeof(MyProjectNameWebModule).Assembly));
builder.PartManager.ApplicationParts.Add(new CompiledRazorAssemblyPart(typeof(MyProjectNameWebModule).Assembly));
});
}

Loading…
Cancel
Save