├── .gitignore
├── Demos
├── Servers
│ ├── OrderServer
│ │ ├── OrderServer.csproj
│ │ └── OrderServicesBuilderOptionsExtension.cs
│ ├── TicketServer
│ │ ├── TicketServer.csproj
│ │ └── TicketServicesBuilderOptionsExtension.cs
│ └── VipCardServer
│ │ ├── VipCardServer.csproj
│ │ └── VipCardServicesBuilderOptionsExtension.cs
├── Xpress.Demo.Api
│ ├── Controllers
│ │ └── ValuesController.cs
│ ├── Filters
│ │ └── JobAuthorizationFilter.cs
│ ├── Models
│ │ └── TestCacheItem.cs
│ ├── NLog.Exceptionless.config
│ ├── NLog.config
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Startup.cs
│ ├── Xpress.Demo.Api.csproj
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ └── wwwroot
│ │ ├── favicon.ico
│ │ ├── swagger
│ │ └── webpack.config.js
│ │ └── webpack.config.js
├── Xpress.Demo.Application
│ ├── ApplicationServicesBuilderOptionsExtension.cs
│ ├── BackgroundJobs
│ │ ├── TestBackGroundJob.cs
│ │ └── TestBackgroundEventArgs.cs
│ ├── CapSubscribers
│ │ └── CapEventSubscriber.cs
│ ├── DemoService.cs
│ ├── IDemoService.cs
│ ├── LocalEventHandlers
│ │ └── TestLocalEventHandler.cs
│ ├── RecurringJobs
│ │ └── TestRecurringJob.cs
│ └── Xpress.Demo.Application.csproj
├── Xpress.Demo.Core
│ ├── CoreServicesBuilderOptionsExtension.cs
│ ├── Events
│ │ ├── TestCapEvent.cs
│ │ └── TestLocalEvent.cs
│ └── Xpress.Demo.Core.csproj
└── Xpress.Demo.EntityFramework
│ ├── DemoDbContext.cs
│ └── Xpress.Demo.EntityFramework.csproj
├── README.md
├── Source
├── Xpress.AspNetCore
│ ├── AspNetCoreServicesBuilderOptionsExtension.cs
│ ├── ExceptionHandling
│ │ ├── DefaultExceptionToErrorInfoConverter.cs
│ │ ├── DefaultHttpExceptionStatusCodeFinder.cs
│ │ ├── ExceptionHttpStatusCodeOptions.cs
│ │ ├── IExceptionToErrorInfoConverter.cs
│ │ ├── IHttpExceptionStatusCodeFinder.cs
│ │ └── XpressExceptionFilter.cs
│ ├── Extensions
│ │ └── ActionDescriptorExtensions.cs
│ ├── ModelValidation
│ │ ├── IModelStateValidator.cs
│ │ ├── IXpressValidationResult.cs
│ │ ├── ModelStateValidator.cs
│ │ ├── XpressModelValidationActionFilter.cs
│ │ └── XpressValidationResult.cs
│ ├── Runtime
│ │ ├── HttpContextCancellationTokenProvider.cs
│ │ └── HttpContextCurrentPrincipalAccessor.cs
│ ├── Uow
│ │ ├── UnitOfWorkMiddleware.cs
│ │ └── UowActionFilter.cs
│ ├── Utils
│ │ └── ActionResultHelper.cs
│ └── Xpress.AspNetCore.csproj
├── Xpress.AutoMapper
│ ├── AutoMapAttribute.cs
│ ├── AutoMapAttributeBase.cs
│ ├── AutoMapExtensions.cs
│ ├── AutoMapFromAttribute.cs
│ ├── AutoMapToAttribute.cs
│ ├── AutoMapperAppBuilderOptionsExtension.cs
│ ├── AutoMapperObjectMapper.cs
│ ├── IObjectMapper.cs
│ └── Xpress.AutoMapper.csproj
├── Xpress.Autofac
│ ├── AutofacIocRegister.cs
│ ├── AutofacIocResolver.cs
│ ├── AutofacServicesBuilderOptionsExtension.cs
│ ├── RegistrationBuilderExtensions.cs
│ └── Xpress.Autofac.csproj
├── Xpress.CastleWindsor
│ ├── ComponentRegistrationExtensions.cs
│ ├── LocalLifetimeScopeAccessor.cs
│ ├── ThreadSafeDefaultLifetimeScope.cs
│ ├── WindsorIocRegister.cs
│ ├── WindsorIocResolver.cs
│ ├── WindsorServicesBuilderExtension.cs
│ └── Xpress.CastleWindsor.csproj
└── Xpress.Core
│ ├── AppBuilderOptions.cs
│ ├── Application
│ ├── ApplicationService.cs
│ └── IApplicationService.cs
│ ├── BackgroundJobs
│ ├── BackgroundEventArgsBase.cs
│ ├── BackgroundJobArgsHelper.cs
│ ├── BackgroundJobConfiguration.cs
│ ├── BackgroundJobExecuter.cs
│ ├── BackgroundJobExecutionException.cs
│ ├── BackgroundJobManagerExtensions.cs
│ ├── BackgroundJobNameAttribute.cs
│ ├── BackgroundJobOptions.cs
│ ├── BackgroundJobPriority.cs
│ ├── HangfireBackgroundJobManager.cs
│ ├── HangfireJobExecutionAdapter.cs
│ ├── IBackgroundEventArgs.cs
│ ├── IBackgroundJob.cs
│ ├── IBackgroundJobExecuter.cs
│ ├── IBackgroundJobManager.cs
│ ├── IBackgroundJobNameProvider.cs
│ ├── JobExecutionContext.cs
│ └── NullBackgroundJobManager.cs
│ ├── Caching
│ ├── CacheNameAttribute.cs
│ ├── DistributedCache.cs
│ └── IDistributedCache.cs
│ ├── Collections
│ ├── ITypeList.cs
│ └── TypeList.cs
│ ├── DependencyInjection
│ ├── DependencyLifeStyle.cs
│ ├── IIocResolver.cs
│ ├── IScopedDependency.cs
│ ├── IServiceProviderAccessor.cs
│ ├── ISingletonDependency.cs
│ ├── ITransientDependency.cs
│ ├── InterceptorBase.cs
│ ├── IocRegisterBase.cs
│ └── IocResolverBase.cs
│ ├── Domain
│ ├── Aggregates
│ │ ├── AggregateEvent.cs
│ │ ├── AggregateName.cs
│ │ ├── AggregateNameAttribute.cs
│ │ ├── AggregateRoot.cs
│ │ ├── AggregateState.cs
│ │ ├── IAggregateEvent.cs
│ │ ├── IAggregateName.cs
│ │ ├── IAggregateRoot.cs
│ │ ├── IEmit.cs
│ │ └── IEventApplier.cs
│ ├── Entities
│ │ ├── Entity.cs
│ │ ├── IEntity.cs
│ │ ├── IHasCreationTime.cs
│ │ ├── IHasDeletionTime.cs
│ │ ├── IHasModificationTime.cs
│ │ ├── IPassivable.cs
│ │ └── ISoftDelete.cs
│ └── Services
│ │ ├── DomainService.cs
│ │ └── IDomainService.cs
│ ├── Dtos
│ ├── DisplayItem.cs
│ ├── DisplayProperty.cs
│ ├── EntityDto.cs
│ ├── ErrorResult.cs
│ ├── IEntityDto.cs
│ ├── IPagingResult.cs
│ ├── IResult.cs
│ ├── PagingResult.cs
│ ├── Result.cs
│ └── ResultCode.cs
│ ├── EntityFramework
│ ├── EfDbContextBase.cs
│ ├── EfDbContextProvider.cs
│ ├── EfRepositoryBaseOfTEntityAndTPrimaryKey.cs
│ ├── IEfDbContextProvider.cs
│ └── RepositoryExtensions.cs
│ ├── EventBus
│ ├── Cap
│ │ ├── CapEventPublisher.cs
│ │ ├── CapTransactionExtensions.cs
│ │ ├── DbContextBasedCapTransaction.cs
│ │ ├── ICapEventPublisher.cs
│ │ ├── ICapEventSubscriber.cs
│ │ └── NullCapPublisher.cs
│ ├── Distributed
│ │ ├── IDistributedEventBus.cs
│ │ ├── IDistributedEventHandler.cs
│ │ └── NullDistributedEventBus.cs
│ ├── EventBase.cs
│ ├── EventNameAttribute.cs
│ ├── GenericEventNameAttribute.cs
│ ├── IEvent.cs
│ ├── IEventNameProvider.cs
│ └── Local
│ │ ├── ActionEventHandler.cs
│ │ ├── EventHandlerDisposeWrapper.cs
│ │ ├── EventHandlerFactoryUnregistrar.cs
│ │ ├── IEventDataWithInheritableGenericArgument.cs
│ │ ├── IEventHandlerDisposeWrapper.cs
│ │ ├── IEventHandlerFactory.cs
│ │ ├── ILocalEventBus.cs
│ │ ├── ILocalEventHandler.cs
│ │ ├── ILocalEventPublisher.cs
│ │ ├── ILocalEventSubscriber.cs
│ │ ├── IocEventHandlerFactory.cs
│ │ ├── LocalEventBus.cs
│ │ ├── LocalEventBusOptions.cs
│ │ ├── NullLocalEventBus.cs
│ │ ├── SingleInstanceHandlerFactory.cs
│ │ └── TransientEventHandlerFactory.cs
│ ├── Exceptions
│ ├── BusinessException.cs
│ ├── EntityNotFoundException.cs
│ ├── HttpRequestExtensions.cs
│ ├── IBusinessException.cs
│ ├── IUserFriendlyException.cs
│ ├── OptimisticConcurrencyException.cs
│ ├── UserFriendlyException.cs
│ ├── XpressAuthorizationException.cs
│ ├── XpressException.cs
│ └── XpressValidationException.cs
│ ├── Extensions
│ ├── CancellationTokenProviderExtensions.cs
│ ├── CollectionExtensions.cs
│ ├── ComparisonOperator.cs
│ ├── DictionaryExtensions.cs
│ ├── EnumerableExtensions.cs
│ ├── EventHandlerExtensions.cs
│ ├── ExceptionExtensions.cs
│ ├── ExpressionExtensions.cs
│ ├── LockExtensions.cs
│ ├── LoggerExtensions.cs
│ ├── ObjectExtensions.cs
│ ├── QueryableExtensions.cs
│ ├── StringExtensions.cs
│ └── TypeExtensions.cs
│ ├── Http
│ ├── MimeTypes.cs
│ ├── RemoteServiceErrorInfo.cs
│ ├── RemoteServiceErrorResponse.cs
│ ├── RemoteServiceValidationErrorInfo.cs
│ └── XpressHttpConsts.cs
│ ├── IHasErrorCode.cs
│ ├── IHasErrorDetails.cs
│ ├── IHasLogLevel.cs
│ ├── IHasValidationErrors.cs
│ ├── Identity
│ ├── GuidProvider.cs
│ ├── IGuidGenerator.cs
│ ├── IIdentity.cs
│ ├── Identity.cs
│ ├── SequentialGuidGenerator.cs
│ └── SequentialGuidType.cs
│ ├── NullDisposable.cs
│ ├── Queries
│ ├── IPagingInfo.cs
│ ├── IPagingQuery.cs
│ ├── IPagingSortInfo.cs
│ ├── IQuery.cs
│ ├── ISortInfo.cs
│ ├── PagingInfo.cs
│ ├── PagingQuery.cs
│ ├── PagingSortInfo.cs
│ ├── Query.cs
│ ├── QueryAttribute.cs
│ ├── QueryExtensions.cs
│ └── SortQuery.cs
│ ├── RecurringJobs
│ ├── IReccuringJobManager.cs
│ └── ReccuringJobManager.cs
│ ├── Repositories
│ ├── AbsRepositoryBase.cs
│ ├── IRepository.cs
│ └── IRepositoryOfTEntityAndTPrimaryKey.cs
│ ├── RetryStrategies
│ ├── IOptimisticConcurrencyRetryStrategy.cs
│ ├── IRetryStrategy.cs
│ ├── OptimisticConcurrencyRetryOption.cs
│ ├── OptimisticConcurrencyRetryStrategy.cs
│ └── Retry.cs
│ ├── Runtime
│ ├── ClaimsExtensions.cs
│ ├── ClaimsUserSession.cs
│ ├── ICurrentPrincipalAccessor.cs
│ ├── IUserSession.cs
│ ├── NullUserSession.cs
│ ├── ThreadCurrentPrincipalAccessor.cs
│ └── XpressClaimTypes.cs
│ ├── Serialization
│ ├── BinarySerializationHelper.cs
│ ├── DefaultObjectSerializer.cs
│ ├── IJsonSerializer.cs
│ ├── IObjectSerializer.cs
│ ├── JsonIsoDateTimeConverter.cs
│ └── NewtonsoftJsonSerializer.cs
│ ├── ServicesBuilderOptions.cs
│ ├── Specifications
│ ├── AllSpecifications.cs
│ ├── AndSpeficication.cs
│ ├── AtLeastSpecification.cs
│ ├── ISpecification.cs
│ ├── NotSpecification.cs
│ ├── OrSpecification.cs
│ └── Specification.cs
│ ├── Threading
│ ├── AsyncHelper.cs
│ ├── AsyncLocalObjectProvider.cs
│ ├── IAsyncLocalObjectProvider.cs
│ ├── ICancellationTokenProvider.cs
│ ├── InternalAsyncHelper.cs
│ └── NullCancellationTokenProvider.cs
│ ├── Timing
│ ├── Clock.cs
│ ├── ClockOptions.cs
│ └── IClock.cs
│ ├── Uow
│ ├── ChildUnitOfWork.cs
│ ├── DefaultUnitOfWorkOptions.cs
│ ├── ISupportsRollback.cs
│ ├── ISupportsSavingChanges.cs
│ ├── IUnitOfWork.cs
│ ├── IUnitOfWorkAccessor.cs
│ ├── IUnitOfWorkEnabled.cs
│ ├── IUnitOfWorkManager.cs
│ ├── IUnitOfWorkOptions.cs
│ ├── UnitOfWork.cs
│ ├── UnitOfWorkAccessor.cs
│ ├── UnitOfWorkAttribute.cs
│ ├── UnitOfWorkEventArgs.cs
│ ├── UnitOfWorkExtensions.cs
│ ├── UnitOfWorkFailedEventArgs.cs
│ ├── UnitOfWorkHelper.cs
│ ├── UnitOfWorkInterceptor.cs
│ ├── UnitOfWorkManager.cs
│ ├── UnitOfWorkOptions.cs
│ └── UnitOfWorkTransactionBehavior.cs
│ ├── Utils
│ ├── CastleProxyHelper.cs
│ ├── Check.cs
│ ├── EntityHelper.cs
│ ├── EnumHelper.cs
│ ├── ReflectionHelper.cs
│ └── XpressAsyncHelper.cs
│ ├── ValueObjects
│ ├── ISingleValueObject.cs
│ ├── SingleValueObject.cs
│ ├── SingleValueObjectConverter.cs
│ └── ValueObject.cs
│ ├── Xpress.Core.csproj
│ ├── XpressAppBuilderExtensions.cs
│ └── XpressServiceCollectionExtensions.cs
└── Xpress.sln
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | #ignore thumbnails created by windows
3 | Thumbs.db
4 | #Ignore files build by Visual Studio
5 | *.obj
6 | *.exe
7 | *.pdb
8 | *.user
9 | *.aps
10 | *.pch
11 | *.vspscc
12 | *_i.c
13 | *_p.c
14 | *.ncb
15 | *.suo
16 | *.tlb
17 | *.tlh
18 | *.bak
19 | *.cache
20 | *.ilk
21 | *.log
22 | [Bb]in
23 | [Dd]ebug*/
24 | *.lib
25 | *.sbr
26 | obj/
27 | [Rr]elease*/
28 | _ReSharper*/
29 | [Tt]est[Rr]esult*
30 |
31 | #Ignore thumbnails created by Windows
32 | #Ignore files built by Visual Studio
33 | .vs/
34 | #Nuget packages folder
35 | packages/
36 |
--------------------------------------------------------------------------------
/Demos/Servers/OrderServer/OrderServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Demos/Servers/OrderServer/OrderServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xpress.Core;
3 |
4 | namespace OrderServer
5 | {
6 | ///
7 | /// Order server extension methods for .
8 | ///
9 | public static class OrderServicesBuilderOptionsExtension
10 | {
11 | ///
12 | /// Add a order server module
13 | ///
14 | public static ServicesBuilderOptions AddOrderServer(this ServicesBuilderOptions servicesBuilderOptions)
15 | {
16 | servicesBuilderOptions.IocRegister.RegisterAssemblyByBasicInterface(servicesBuilderOptions,typeof(OrderServicesBuilderOptionsExtension).Assembly);
17 |
18 | return servicesBuilderOptions;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Demos/Servers/TicketServer/TicketServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Demos/Servers/TicketServer/TicketServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xpress.Core;
3 |
4 | namespace TicketServer
5 | {
6 | ///
7 | /// ticket server extension methods for .
8 | ///
9 | public static class TicketServicesBuilderOptionsExtension
10 | {
11 | ///
12 | /// Add a ticket server module
13 | ///
14 | public static ServicesBuilderOptions AddTicketServer(this ServicesBuilderOptions servicesBuilderOptions)
15 | {
16 | servicesBuilderOptions.IocRegister.RegisterAssemblyByBasicInterface(servicesBuilderOptions, typeof(TicketServicesBuilderOptionsExtension).Assembly);
17 | return servicesBuilderOptions;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Demos/Servers/VipCardServer/VipCardServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Demos/Servers/VipCardServer/VipCardServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xpress.Core;
3 |
4 | namespace VipCardServer
5 | {
6 | ///
7 | /// vip card extension methods for .
8 | ///
9 | public static class VipCardServicesBuilderOptionsExtension
10 | {
11 | ///
12 | /// Add a vip card module
13 | ///
14 | public static ServicesBuilderOptions AddVipCardServer(this ServicesBuilderOptions servicesBuilderOptions)
15 | {
16 | servicesBuilderOptions.IocRegister.RegisterAssemblyByBasicInterface(servicesBuilderOptions, typeof(VipCardServicesBuilderOptionsExtension).Assembly);
17 | return servicesBuilderOptions;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/Filters/JobAuthorizationFilter.cs:
--------------------------------------------------------------------------------
1 | using Exceptionless;
2 | using Exceptionless.Logging;
3 | using Hangfire.Dashboard;
4 | using Microsoft.AspNetCore.Hosting;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 |
10 | namespace Xpress.Demo.Api.Filters
11 | {
12 | ///
13 | public class JobAuthorizationFilter : IDashboardAuthorizationFilter
14 | {
15 | private readonly IHostingEnvironment _hostingEnvironment;
16 |
17 | ///
18 | public JobAuthorizationFilter(IHostingEnvironment hostingEnvironment)
19 | {
20 | _hostingEnvironment = hostingEnvironment;
21 | }
22 |
23 | ///
24 | public bool Authorize(DashboardContext context)
25 | {
26 | if (_hostingEnvironment.IsProduction()) //非测试环境
27 | return false;
28 | else
29 | {
30 | ExceptionlessClient.Default
31 | .CreateLog(nameof(JobAuthorizationFilter), $"job请求访问地址:{context.Request.RemoteIpAddress}", LogLevel.Fatal).Submit();
32 | return true;
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/Models/TestCacheItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace Xpress.Demo.Api.Models
7 | {
8 | [Serializable]
9 | public class TestCacheItem
10 | {
11 | public string Name { get; private set; }
12 |
13 |
14 | public TestCacheItem(string name)
15 | {
16 | Name = name;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/NLog.Exceptionless.config:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/NLog.config:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:32308",
8 | "sslPort": 44304
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "swagger/index.html",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "Xpress.Demo.Api": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "swagger/index.html",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | },
9 | "ConnectionStrings": {
10 | //"Default": "server=10.99.59.183,1433;database=XpresssDemo;uid=sa;pwd=LZL1314525?",
11 | "Default": "server=10.99.59.183;port=3306;database=XpressDemo;uid=root;pwd=lzl1314525?",
12 | "CacheRedis": "10.99.59.183:6379,password=LZL1314525?,defaultDatabase=10,connectTimeout=1000,connectRetry=3,syncTimeout=10000",
13 | "JobRedis": "10.99.59.183:6379,password=LZL1314525?,allowAdmin=true,defaultDatabase=11,connectTimeout=1000,connectRetry=3,syncTimeout=10000"
14 | },
15 | "ApolloConfig": {
16 | "AppId": "Xpress-Demo-Api",
17 | "MetaServer": "http://10.98.0.232:9100"
18 | },
19 | "Exceptionless": {
20 | "ServerUrl": "http://10.98.98.175:9001",
21 | "ApiKey": "QI7Mokkw5mnRfWs1ka4WsSpB4gFbS8E0XezwWizH"
22 | },
23 | "RabbitMq": {
24 | "HostName": "10.98.0.233",
25 | "VirtualHost": "/",
26 | "UserName": "ThemePark",
27 | "Password": "123456",
28 | "Port": 5673
29 | },
30 | //"RabbitMq": {
31 | // "HostName": "127.0.0.1",
32 | // "VirtualHost": "/",
33 | // "UserName": "guest",
34 | // "Password": "guest",
35 | // "Port": 5672
36 | //}
37 | }
38 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information"
5 | }
6 | },
7 | "AllowedHosts": "*"
8 | }
9 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XF1314/Xpress/b99841d14e8dc03128afbdad68310da2be3aa435/Demos/Xpress.Demo.Api/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/wwwroot/swagger/webpack.config.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Api/wwwroot/webpack.config.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/ApplicationServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xpress.Core;
3 |
4 | namespace Xpress.Demo.Application
5 | {
6 | ///
7 | /// Demo application module extension methods for .
8 | ///
9 | public static class ApplicationServicesBuilderOptionsExtension
10 | {
11 | ///
12 | /// Add a application demo module
13 | ///
14 | public static ServicesBuilderOptions AddDemoApplication(this ServicesBuilderOptions servicesBuilderOptions)
15 | {
16 | servicesBuilderOptions.IocRegister.RegisterAssemblyByBasicInterface(servicesBuilderOptions, typeof(ApplicationServicesBuilderOptionsExtension).Assembly);
17 | return servicesBuilderOptions;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/BackgroundJobs/TestBackGroundJob.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using Xpress.Core.BackgroundJobs;
6 | using Xpress.Core.DependencyInjection;
7 |
8 | namespace Xpress.Demo.Application.BackgroundJobs
9 | {
10 | ///
11 | public class TestBackGroundJob : IBackgroundJob, ITransientDependency
12 | {
13 | private readonly ILogger _logger;
14 |
15 | ///
16 | public TestBackGroundJob(ILogger logger)
17 | {
18 | _logger = logger;
19 | }
20 |
21 | ///
22 | public void Execute(TestBackgroundEventArgs args)
23 | {
24 | _logger.LogInformation(args.Message);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/BackgroundJobs/TestBackgroundEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.BackgroundJobs;
5 |
6 | namespace Xpress.Demo.Application.BackgroundJobs
7 | {
8 | public class TestBackgroundEventArgs : BackgroundEventArgsBase
9 | {
10 | public string Message { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/CapSubscribers/CapEventSubscriber.cs:
--------------------------------------------------------------------------------
1 | using DotNetCore.CAP;
2 | using Exceptionless;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.Logging.Abstractions;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using Xpress.Core.DependencyInjection;
10 | using Xpress.Core.EventBus.Cap;
11 | using Xpress.Core.Uow;
12 | using Xpress.Demo.Core.Events;
13 |
14 | namespace Xpress.Demo.Application.CapSubscribers
15 | {
16 | public class CapEventSubscriber : ICapEventSubscriber
17 | {
18 | private readonly IServiceProvider _serviceProvider;
19 | private readonly ILogger _logger;
20 | private readonly IUnitOfWorkManager _unitOfWorkManager;
21 |
22 | public CapEventSubscriber(IServiceProvider serviceProvider, ILogger logger ,IUnitOfWorkManager unitOfWorkManager)
23 | {
24 | _logger = logger;
25 | _serviceProvider = serviceProvider;
26 | _unitOfWorkManager = unitOfWorkManager;
27 | }
28 |
29 | [CapSubscribe("TestCap")]
30 | public async Task TestCap(TestCapEvent testCapEvent)
31 | {
32 | _logger.LogInformation(testCapEvent.Message);
33 | ExceptionlessClient.Default.CreateLog(nameof(CapEventSubscriber), testCapEvent.Message, Exceptionless.Logging.LogLevel.Fatal).Submit();
34 |
35 | await Task.CompletedTask;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/DemoService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Microsoft.Extensions.Logging.Abstractions;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using Xpress.Core.Application;
7 |
8 | namespace Xpress.Demo.Application
9 | {
10 | public class DemoService : ApplicationService, IDemoService
11 | {
12 | public ILogger Logger { get; set; }
13 |
14 | public DemoService(ILogger logger)
15 | {
16 | Logger = NullLogger.Instance;
17 | }
18 |
19 | public void WriteMessage(string message)
20 | {
21 | Logger.LogCritical(message);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/IDemoService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.Application;
5 |
6 | namespace Xpress.Demo.Application
7 | {
8 | public interface IDemoService : IApplicationService
9 | {
10 | void WriteMessage(string message);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/LocalEventHandlers/TestLocalEventHandler.cs:
--------------------------------------------------------------------------------
1 | using Exceptionless;
2 | using Microsoft.Extensions.Logging;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Xpress.Core.DependencyInjection;
8 | using Xpress.Core.EventBus.Local;
9 | using Xpress.Demo.Application.CapSubscribers;
10 | using Xpress.Demo.Core.Events;
11 |
12 | namespace Xpress.Demo.Application.LocalEventHandlers
13 | {
14 | public class TestLocalEventHandler : ILocalEventHandler, ITransientDependency
15 | {
16 | private readonly IServiceProvider _serviceProvider;
17 | private readonly ILogger _logger;
18 |
19 | public TestLocalEventHandler(IServiceProvider serviceProvider, ILogger logger)
20 | {
21 | _logger = logger;
22 | _serviceProvider = serviceProvider;
23 | }
24 |
25 | public async Task HandleEventAsync(TestLocalEvent @event)
26 | {
27 | _logger.LogCritical(@event.Message);
28 | //ExceptionlessClient.Default.CreateLog(nameof(TestLocalEventHandler), @event.Message, Exceptionless.Logging.LogLevel.Fatal).Submit();
29 |
30 | await Task.CompletedTask;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/RecurringJobs/TestRecurringJob.cs:
--------------------------------------------------------------------------------
1 | using Hangfire.RecurringJobExtensions;
2 | using Hangfire.Server;
3 | using Microsoft.Extensions.Logging;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Text;
7 | using Xpress.Core.DependencyInjection;
8 |
9 | namespace Xpress.Demo.Application.RecurringJobs
10 | {
11 | ///
12 | public class TestRecurringJob : IRecurringJob, ITransientDependency
13 | {
14 | private readonly ILogger _logger;
15 |
16 | ///
17 | public TestRecurringJob(ILogger logger)
18 | {
19 | _logger = logger;
20 | }
21 |
22 | ///
23 | /// Job Excution
24 | ///
25 | [RecurringJob("00 02 * * *", "China Standard Time", "default")]
26 | public void Execute(PerformContext context)
27 | {
28 | _logger.LogInformation("RecuringJobTest...");
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Application/Xpress.Demo.Application.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 | bin\Debug\netcoreapp2.2\Xpress.Demo.Application.xml
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Core/CoreServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xpress.Core;
3 |
4 | namespace Xpress.Demo.Core
5 | {
6 | ///
7 | /// Demo core extension methods for .
8 | ///
9 | public static class CoreServicesBuilderOptionsExtension
10 | {
11 | ///
12 | /// Add a core demo module
13 | ///
14 | public static ServicesBuilderOptions AddDemoCore(this ServicesBuilderOptions servicesBuilderOptions)
15 | {
16 | servicesBuilderOptions.IocRegister.RegisterAssemblyByBasicInterface(servicesBuilderOptions, typeof(CoreServicesBuilderOptionsExtension).Assembly);
17 | return servicesBuilderOptions;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Core/Events/TestCapEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.EventBus;
5 |
6 | namespace Xpress.Demo.Core.Events
7 | {
8 | public class TestCapEvent : EventBase
9 | {
10 | public string Message { get; set; }
11 |
12 | public TestCapEvent(string eventName= default(string)) : base(eventName)
13 | {
14 |
15 | }
16 |
17 | public override string GetEventName()
18 | {
19 | return "TestCap";
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Core/Events/TestLocalEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.EventBus;
5 |
6 | namespace Xpress.Demo.Core.Events
7 | {
8 | public class TestLocalEvent : EventBase
9 | {
10 | public string Message { get; set; }
11 |
12 | public TestLocalEvent(string eventName = default(string)) : base(eventName)
13 | {
14 |
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.Core/Xpress.Demo.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.EntityFramework/DemoDbContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using Xpress.Core.EntityFramework;
6 |
7 | namespace Xpress.Demo.EntityFramework
8 | {
9 | public class DemoDbContext : EfDbContextBase
10 | {
11 | ///
12 | /// 唯一标识
13 | ///
14 | public string Id { get; private set; }
15 |
16 | public DemoDbContext(DbContextOptions options)
17 | : base(options)
18 | {
19 | Id = Guid.NewGuid().ToString("N");
20 | }
21 |
22 | public override void Dispose()
23 | {
24 | base.Dispose();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Demos/Xpress.Demo.EntityFramework/Xpress.Demo.EntityFramework.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Xpress
2 | 一个轻量级面向服务的Asp.Net Core项目框架,基于Ioc容器(Autofac或者Castle)实现了服务自动注册, 集成了Apollo配置中心,CAP的事件总线,内存事件总线,Hangfire后台任务&定时任务,Exceptionless&Nlog日志组件,Redis分布式缓存具备工作单元、领域驱动等特性。框架的远景是集成Ids4身份认证,Consul服务注册等组件,以完成对基于Ocelot+Consul+Ids4的微服务解决方案支持。
3 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/AspNetCoreServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core;
5 |
6 | namespace Xpress.AspNetCore
7 | {
8 | ///
9 | ///AspNetCore extension methods for .
10 | ///
11 | public static class AspNetCoreServicesBuilderOptionsExtension
12 | {
13 | ///
14 | /// Add a aspNetCore module
15 | ///
16 | public static ServicesBuilderOptions AddAspNetCore(this ServicesBuilderOptions servicesBuilderOptions)
17 | {
18 | servicesBuilderOptions.IocRegister.RegisterAssemblyByBasicInterface(servicesBuilderOptions, typeof(AspNetCoreServicesBuilderOptionsExtension).Assembly);
19 | return servicesBuilderOptions;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ExceptionHandling/ExceptionHttpStatusCodeOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net;
4 | using System.Text;
5 |
6 | namespace Xpress.AspNetCore.ExceptionHandling
7 | {
8 | public class ExceptionHttpStatusCodeOptions
9 | {
10 | public IDictionary ErrorCodeToHttpStatusCodeMappings { get; }
11 |
12 | public ExceptionHttpStatusCodeOptions()
13 | {
14 | ErrorCodeToHttpStatusCodeMappings = new Dictionary();
15 | }
16 |
17 | public void Map(string errorCode, HttpStatusCode httpStatusCode)
18 | {
19 | ErrorCodeToHttpStatusCodeMappings[errorCode] = httpStatusCode;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.Http;
5 |
6 | namespace Xpress.AspNetCore.ExceptionHandling
7 | {
8 | ///
9 | /// This interface can be implemented to convert an object to an object.
10 | /// Implements Chain Of Responsibility pattern.
11 | ///
12 | public interface IExceptionToErrorInfoConverter
13 | {
14 | ///
15 | /// Converter method.
16 | ///
17 | /// The exception
18 | /// Error info or null
19 | RemoteServiceErrorInfo Convert(Exception exception);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ExceptionHandling/IHttpExceptionStatusCodeFinder.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Net;
5 | using System.Text;
6 |
7 | namespace Xpress.AspNetCore.ExceptionHandling
8 | {
9 | public interface IHttpExceptionStatusCodeFinder
10 | {
11 | HttpStatusCode GetStatusCode(HttpContext httpContext, Exception exception);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/Extensions/ActionDescriptorExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.Abstractions;
2 | using Microsoft.AspNetCore.Mvc.Controllers;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Reflection;
6 | using System.Text;
7 | using Xpress.AspNetCore.Utils;
8 | using Xpress.Core.Exceptions;
9 |
10 | namespace Xpress.AspNetCore.Extensions
11 | {
12 | public static class ActionDescriptorExtensions
13 | {
14 | public static ControllerActionDescriptor AsControllerActionDescriptor(this ActionDescriptor actionDescriptor)
15 | {
16 | if (!actionDescriptor.IsControllerAction())
17 | {
18 | throw new XpressException($"{nameof(actionDescriptor)} should be type of {typeof(ControllerActionDescriptor).AssemblyQualifiedName}");
19 | }
20 |
21 | return actionDescriptor as ControllerActionDescriptor;
22 | }
23 |
24 | public static MethodInfo GetMethodInfo(this ActionDescriptor actionDescriptor)
25 | {
26 | return actionDescriptor.AsControllerActionDescriptor().MethodInfo;
27 | }
28 |
29 | public static Type GetReturnType(this ActionDescriptor actionDescriptor)
30 | {
31 | return actionDescriptor.GetMethodInfo().ReturnType;
32 | }
33 |
34 | public static bool HasObjectResult(this ActionDescriptor actionDescriptor)
35 | {
36 | return ActionResultHelper.IsObjectResult(actionDescriptor.GetReturnType());
37 | }
38 |
39 | public static bool IsControllerAction(this ActionDescriptor actionDescriptor)
40 | {
41 | return actionDescriptor is ControllerActionDescriptor;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ModelValidation/IModelStateValidator.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.ModelBinding;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | namespace Xpress.AspNetCore.ModelValidation
7 | {
8 | public interface IModelStateValidator
9 | {
10 | void Validate(ModelStateDictionary modelState);
11 |
12 | void AddErrors(IXpressValidationResult validationResult, ModelStateDictionary modelState);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ModelValidation/IXpressValidationResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Text;
5 |
6 | namespace Xpress.AspNetCore.ModelValidation
7 | {
8 | public interface IXpressValidationResult
9 | {
10 | List Errors { get; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ModelValidation/ModelStateValidator.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.ModelBinding;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel.DataAnnotations;
5 | using System.Linq;
6 | using System.Text;
7 | using Xpress.Core.DependencyInjection;
8 | using Xpress.Core.Exceptions;
9 |
10 | namespace Xpress.AspNetCore.ModelValidation
11 | {
12 | public class ModelStateValidator : IModelStateValidator, ITransientDependency
13 | {
14 | public virtual void Validate(ModelStateDictionary modelState)
15 | {
16 | var validationResult = new XpressValidationResult();
17 |
18 | AddErrors(validationResult, modelState);
19 |
20 | if (validationResult.Errors.Any())
21 | {
22 | throw new XpressValidationException(
23 | "ModelState 验证未通过,具体原因看详情。",
24 | validationResult.Errors
25 | );
26 | }
27 | }
28 |
29 | public virtual void AddErrors(IXpressValidationResult validationResult, ModelStateDictionary modelState)
30 | {
31 | if (modelState.IsValid)
32 | {
33 | return;
34 | }
35 |
36 | foreach (var state in modelState)
37 | {
38 | foreach (var error in state.Value.Errors)
39 | {
40 | validationResult.Errors.Add(new ValidationResult(error.ErrorMessage, new[] { state.Key }));
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ModelValidation/XpressModelValidationActionFilter.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc.Filters;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xpress.AspNetCore.Extensions;
7 | using Xpress.Core.DependencyInjection;
8 |
9 | namespace Xpress.AspNetCore.ModelValidation
10 | {
11 | public class XpressModelValidationActionFilter : IAsyncActionFilter, ITransientDependency
12 | {
13 | private readonly IModelStateValidator _validator;
14 |
15 | public XpressModelValidationActionFilter(IModelStateValidator validator)
16 | {
17 | _validator = validator;
18 | }
19 |
20 | public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
21 | {
22 | //TODO: Configuration to disable validation for controllers..?
23 |
24 | if (context.ActionDescriptor.IsControllerAction() && context.ActionDescriptor.HasObjectResult())
25 | {
26 | _validator.Validate(context.ModelState);
27 | }
28 |
29 | await next();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/ModelValidation/XpressValidationResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Text;
5 |
6 | namespace Xpress.AspNetCore.ModelValidation
7 | {
8 | public class XpressValidationResult : IXpressValidationResult
9 | {
10 | public List Errors { get; }
11 |
12 | public XpressValidationResult()
13 | {
14 | Errors = new List();
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/Runtime/HttpContextCancellationTokenProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading;
6 | using Xpress.Core.DependencyInjection;
7 | using Xpress.Core.Threading;
8 |
9 | namespace Xpress.AspNetCore.Runtime
10 | {
11 | public class HttpContextCancellationTokenProvider : ICancellationTokenProvider, ITransientDependency
12 | {
13 | public CancellationToken Token => _httpContextAccessor.HttpContext?.RequestAborted ?? default(CancellationToken);
14 |
15 | private readonly IHttpContextAccessor _httpContextAccessor;
16 |
17 | public HttpContextCancellationTokenProvider(IHttpContextAccessor httpContextAccessor)
18 | {
19 | _httpContextAccessor = httpContextAccessor;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/Runtime/HttpContextCurrentPrincipalAccessor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Security.Claims;
5 | using System.Text;
6 | using Xpress.Core.Runtime;
7 |
8 | namespace Xpress.AspNetCore.Runtime
9 | {
10 | public class HttpContextCurrentPrincipalAccessor : ThreadCurrentPrincipalAccessor
11 | {
12 | public override ClaimsPrincipal Principal => _httpContextAccessor.HttpContext?.User ?? base.Principal;
13 |
14 | private readonly IHttpContextAccessor _httpContextAccessor;
15 |
16 | public HttpContextCurrentPrincipalAccessor(IHttpContextAccessor httpContextAccessor)
17 | {
18 | _httpContextAccessor = httpContextAccessor;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/Uow/UnitOfWorkMiddleware.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xpress.Core.Uow;
7 |
8 | namespace Xpress.AspNetCore.Uow
9 | {
10 | public class UnitOfWorkMiddleware
11 | {
12 | public const string UnitOfWorkReservationName = "_ActionUnitOfWork";
13 |
14 | private readonly RequestDelegate _next;
15 | private readonly IUnitOfWorkManager _unitOfWorkManager;
16 |
17 | public UnitOfWorkMiddleware(RequestDelegate next, IUnitOfWorkManager unitOfWorkManager)
18 | {
19 | _next = next;
20 | _unitOfWorkManager = unitOfWorkManager;
21 | }
22 |
23 | public async Task Invoke(HttpContext httpContext)
24 | {
25 | using (var uow = _unitOfWorkManager.Reserve(UnitOfWorkReservationName))
26 | {
27 | await _next(httpContext);
28 | await uow.CompleteAsync(httpContext.RequestAborted);
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/Utils/ActionResultHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using Xpress.Core.Threading;
7 | using Xpress.Core;
8 | using Xpress.Core.Utils;
9 |
10 | namespace Xpress.AspNetCore.Utils
11 | {
12 | public static class ActionResultHelper
13 | {
14 | public static List ObjectResultTypes { get; }
15 |
16 | static ActionResultHelper()
17 | {
18 | ObjectResultTypes = new List
19 | {
20 | typeof(JsonResult),
21 | typeof(ObjectResult),
22 | typeof(NoContentResult)
23 | };
24 | }
25 |
26 | public static bool IsObjectResult(Type returnType)
27 | {
28 | returnType = XpressAsyncHelper.UnwrapTask(returnType);
29 |
30 | if (!typeof(IActionResult).IsAssignableFrom(returnType))
31 | {
32 | return true;
33 | }
34 |
35 | return ObjectResultTypes.Any(t => t.IsAssignableFrom(returnType));
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Source/Xpress.AspNetCore/Xpress.AspNetCore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using AutoMapper;
3 |
4 | namespace Xpress.AutoMapper
5 | {
6 | ///
7 | /// Mark as a two-way mapping
8 | ///
9 | public class AutoMapAttribute : AutoMapAttributeBase
10 | {
11 | ///
12 | /// Create a two-way entity mapping relationship
13 | ///
14 | public override void CreateMap(IMapperConfigurationExpression configuration, Type type)
15 | {
16 | CreateMap(configuration, type, MemberList.Destination);
17 | CreateMap(configuration, type, MemberList.Source);
18 | }
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapAttributeBase.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using System;
3 |
4 | namespace Xpress.AutoMapper
5 | {
6 | ///
7 | /// Mapping relationships need to inherit abstract base classes
8 | ///
9 | public abstract class AutoMapAttributeBase : Attribute
10 | {
11 | ///
12 | /// Target type
13 | ///
14 | public Type[] TargetTypes { get; private set; }
15 |
16 | ///
17 | protected AutoMapAttributeBase(params Type[] targetTypes)
18 | {
19 | TargetTypes = targetTypes;
20 | }
21 |
22 | ///
23 | /// Create a specified mapping
24 | ///
25 | protected void CreateMap(IMapperConfigurationExpression configuration, Type type, MemberList memberList)
26 | {
27 | if (TargetTypes == null)
28 | {
29 | return;
30 | }
31 |
32 | foreach (var targetType in TargetTypes)
33 | {
34 | configuration.CreateMap(targetType, type, memberList);
35 | }
36 | }
37 |
38 | ///
39 | /// Create mappings
40 | ///
41 | public abstract void CreateMap(IMapperConfigurationExpression configuration, Type type);
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapExtensions.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | namespace Xpress.AutoMapper
4 | {
5 | ///
6 | /// Object mapping extension
7 | ///
8 | public static class ObjectMapperExtensions
9 | {
10 | ///
11 | /// Map out new target objects
12 | ///
13 | public static TDestination MapTo(this object source)
14 | {
15 | return Mapper.Map(source);
16 | }
17 |
18 | ///
19 | /// Map attribute content to target object
20 | ///
21 | public static TDestination MapTo(this TSource source, TDestination destination)
22 | {
23 | return Mapper.Map(source, destination);
24 | }
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapFromAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using AutoMapper;
3 |
4 | namespace Xpress.AutoMapper
5 | {
6 | ///
7 | /// Mark target object mapped to this object
8 | ///
9 | public class AutoMapFromAttribute : AutoMapAttributeBase
10 | {
11 | ///
12 | public override void CreateMap(IMapperConfigurationExpression configuration, Type type)
13 | {
14 | CreateMap(configuration, type, MemberList.Destination);
15 | }
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapToAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using AutoMapper;
3 |
4 | namespace Xpress.AutoMapper
5 | {
6 | ///
7 | /// Tag mapping to target object
8 | ///
9 | public class AutoMapToAttribute : AutoMapAttributeBase
10 | {
11 | ///
12 | public override void CreateMap(IMapperConfigurationExpression configuration, Type type)
13 | {
14 | CreateMap(configuration, type, MemberList.Source);
15 | }
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapperAppBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using System;
3 | using Xpress.Core;
4 |
5 | namespace Xpress.AutoMapper
6 | {
7 | ///
8 | /// AutoMapper specific extension methods for .
9 | ///
10 | public static class AutoMapperAppBuilderOptionsExtension
11 | {
12 | ///
13 | /// Use AutoMapper
14 | ///
15 | public static AppBuilderOptions UseAutoMapper(this AppBuilderOptions builder, Action config = null)
16 | {
17 | Mapper.Initialize(options =>
18 | {
19 | options.ValidateInlineMaps = false;
20 | config?.Invoke(options);
21 | });
22 |
23 | return builder;
24 | }
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/AutoMapperObjectMapper.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | namespace Xpress.AutoMapper
4 | {
5 | ///
6 | /// Use Automapper mapping
7 | ///
8 | public class AutoMapperObjectMapper : IObjectMapper
9 | {
10 | private readonly IMapper _mapper;
11 |
12 | ///
13 | public AutoMapperObjectMapper(IMapper mapper)
14 | {
15 | _mapper = mapper;
16 | }
17 |
18 | ///
19 | public TDestination Map(object source)
20 | {
21 | return _mapper.Map(source);
22 | }
23 |
24 | ///
25 | public TDestination Map(TSource source, TDestination destination)
26 | {
27 | return _mapper.Map(source, destination);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/IObjectMapper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.AutoMapper
6 | {
7 | ///
8 | /// Defines a simple interface to map objects.
9 | ///
10 | public interface IObjectMapper
11 | {
12 | ///
13 | /// Converts an object to another.
14 | ///
15 | TDestination Map(object source);
16 |
17 | ///
18 | /// Execute a mapping from the source object to the existing destination object
19 | ///
20 | TDestination Map(TSource source, TDestination destination);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Source/Xpress.AutoMapper/Xpress.AutoMapper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Source/Xpress.Autofac/AutofacServicesBuilderOptionsExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core;
5 | using Xpress.Core.DependencyInjection;
6 |
7 | namespace Xpress.Autofac
8 | {
9 | ///
10 | /// Autofac specific extension methods for .
11 | ///
12 | public static class AutofacServicesBuilderOptionsExtension
13 | {
14 | ///
15 | /// Use Autofac as an injection container
16 | ///
17 | public static ServicesBuilderOptions UseAutofac(this ServicesBuilderOptions servicesBuilderOptions)
18 | {
19 | servicesBuilderOptions.IocRegister = new AutofacIocRegister();
20 | servicesBuilderOptions.IocRegister.Register(DependencyLifeStyle.Transient);
21 | return servicesBuilderOptions;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Source/Xpress.Autofac/RegistrationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Autofac.Builder;
2 | using System;
3 | using Xpress.Core.DependencyInjection;
4 |
5 | namespace Xpress.Autofac
6 | {
7 | ///
8 | /// Autofac RegistrationBuilder extensions
9 | ///
10 | public static class RegistrationBuilderExtensions
11 | {
12 | ///
13 | /// Lifestyle conversion and application
14 | ///
15 | public static void AddLifeStyle(this IRegistrationBuilder registration,
16 | DependencyLifeStyle lifeStyle)
17 | {
18 | switch (lifeStyle)
19 | {
20 | case DependencyLifeStyle.Transient:
21 | registration.InstancePerDependency();
22 | break;
23 | case DependencyLifeStyle.Scoped:
24 | registration.InstancePerLifetimeScope();
25 | break;
26 | case DependencyLifeStyle.Singleton:
27 | registration.SingleInstance();
28 | break;
29 | default:
30 | throw new ArgumentException(nameof(lifeStyle));
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Source/Xpress.Autofac/Xpress.Autofac.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Source/Xpress.CastleWindsor/ComponentRegistrationExtensions.cs:
--------------------------------------------------------------------------------
1 | using Castle.MicroKernel.Registration;
2 | using System;
3 | using Xpress.Core.DependencyInjection;
4 |
5 | namespace Xpress.CastleWindsor
6 | {
7 | ///
8 | /// Windsor ComponentRegistration extensions
9 | ///
10 | public static class ComponentRegistrationExtensions
11 | {
12 | ///
13 | /// Lifestyle conversion and application
14 | ///
15 | public static ComponentRegistration ApplyLifestyle(this ComponentRegistration registration, DependencyLifeStyle lifeStyle)
16 | where T : class
17 | {
18 | switch (lifeStyle)
19 | {
20 | case DependencyLifeStyle.Transient:
21 | return registration.LifestyleTransient();
22 | case DependencyLifeStyle.Scoped:
23 | return registration.LifestyleScoped();
24 | case DependencyLifeStyle.Singleton:
25 | return registration.LifestyleSingleton();
26 | default:
27 | throw new ArgumentException(nameof(lifeStyle));
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Source/Xpress.CastleWindsor/LocalLifetimeScopeAccessor.cs:
--------------------------------------------------------------------------------
1 | using Castle.MicroKernel.Context;
2 | using Castle.MicroKernel.Lifestyle.Scoped;
3 | using System.Threading;
4 |
5 | namespace Xpress.CastleWindsor
6 | {
7 | ///
8 | /// Implement a lifetimescope like Autofac
9 | ///
10 | public class LocalLifetimeScopeAccessor : IScopeAccessor
11 | {
12 | private static readonly AsyncLocal AsyncLocalScope = new AsyncLocal();
13 |
14 | ///
15 | public ILifetimeScope GetScope(CreationContext context)
16 | {
17 | if (AsyncLocalScope.Value == null)
18 | {
19 | AsyncLocalScope.Value = new ThreadSafeDefaultLifetimeScope();
20 | }
21 | return AsyncLocalScope.Value;
22 | }
23 |
24 | ///
25 | public void Dispose()
26 | {
27 | AsyncLocalScope.Value.Dispose();
28 | AsyncLocalScope.Value = null;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Source/Xpress.CastleWindsor/ThreadSafeDefaultLifetimeScope.cs:
--------------------------------------------------------------------------------
1 | using Castle.Core;
2 | using Castle.MicroKernel;
3 | using Castle.MicroKernel.Lifestyle.Scoped;
4 | using System;
5 |
6 | namespace Xpress.CastleWindsor
7 | {
8 | ///
9 | /// Default lifetimescope within the scope of a secure thread
10 | ///
11 | public class ThreadSafeDefaultLifetimeScope : ILifetimeScope
12 | {
13 | private static readonly Action _emptyOnAfterCreated = delegate { };
14 | private readonly object _syncLock = new object();
15 | private readonly Action _onAfterCreated;
16 | private IScopeCache _scopeCache;
17 |
18 | ///
19 | public ThreadSafeDefaultLifetimeScope(IScopeCache scopeCache = null, Action onAfterCreated = null)
20 | {
21 | this._scopeCache = scopeCache ?? new ScopeCache();
22 | this._onAfterCreated = onAfterCreated ?? _emptyOnAfterCreated;
23 | }
24 |
25 | ///
26 | public void Dispose()
27 | {
28 | lock (_syncLock)
29 | {
30 | if (_scopeCache == null) return;
31 | if (_scopeCache is IDisposable disposableCache)
32 | {
33 | disposableCache.Dispose();
34 | }
35 | _scopeCache = null;
36 | }
37 | }
38 |
39 | ///
40 | public Burden GetCachedInstance(ComponentModel model, ScopedInstanceActivationCallback createInstance)
41 | {
42 | lock (_syncLock)
43 | {
44 | var burden = _scopeCache[model];
45 | if (burden == null)
46 | {
47 | _scopeCache[model] = burden = createInstance(_onAfterCreated);
48 | }
49 | return burden;
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Source/Xpress.CastleWindsor/WindsorIocResolver.cs:
--------------------------------------------------------------------------------
1 | using Castle.Windsor;
2 | using System;
3 | using Xpress.Core.DependencyInjection;
4 |
5 | namespace Xpress.CastleWindsor
6 | {
7 | ///
8 | public class WindsorIocResolver : IocResolverBase
9 | {
10 | private readonly IWindsorContainer _container;
11 |
12 | ///
13 | public WindsorIocResolver(IWindsorContainer container)
14 | {
15 | _container = container;
16 | }
17 |
18 | ///
19 | public override object Resolve(Type serviceType, object argumentsAsAnonymousType = null)
20 | {
21 | if (argumentsAsAnonymousType == null)
22 | {
23 | return _container.Resolve(serviceType);
24 | }
25 | return _container.Resolve(serviceType, argumentsAsAnonymousType);
26 | }
27 |
28 | ///
29 | public override bool IsRegistered(Type serviceType)
30 | {
31 | return _container.Kernel.HasComponent(serviceType);
32 | }
33 |
34 | ///
35 | public override void Release(object obj)
36 | {
37 | _container.Release(obj);
38 | }
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/Source/Xpress.CastleWindsor/WindsorServicesBuilderExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core;
5 | using Xpress.Core.DependencyInjection;
6 |
7 | namespace Xpress.CastleWindsor
8 | {
9 | ///
10 | /// Castle Windsor specific extension methods for .
11 | ///
12 | public static class WindsorServicesBuilderExtension
13 | {
14 | ///
15 | /// Use Castle Windsor as an injection container
16 | ///
17 | public static ServicesBuilderOptions UseWindsor(this ServicesBuilderOptions servicesBuilderOptions)
18 | {
19 | servicesBuilderOptions.IocRegister = new WindsorIocRegister();
20 | servicesBuilderOptions.IocRegister.Register(DependencyLifeStyle.Transient);
21 | return servicesBuilderOptions;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Source/Xpress.CastleWindsor/Xpress.CastleWindsor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.2
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/AppBuilderOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.DependencyInjection;
5 |
6 | namespace Xpress.Core
7 | {
8 | ///
9 | /// Application framework usage
10 | ///
11 | public class AppBuilderOptions
12 | {
13 | ///
14 | /// Ioc resolver
15 | ///
16 | public readonly IIocResolver IocResolver;
17 |
18 | ///
19 | public AppBuilderOptions(IIocResolver iocResolver)
20 | {
21 | IocResolver = iocResolver;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/Application/ApplicationService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.Application
6 | {
7 | ///
8 | public abstract class ApplicationService : IApplicationService
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/Application/IApplicationService.cs:
--------------------------------------------------------------------------------
1 | using Xpress.Core.DependencyInjection;
2 |
3 | namespace Xpress.Core.Application
4 | {
5 | ///
6 | /// Application layer service interface, application services should inherit this interface
7 | ///
8 | public interface IApplicationService : ITransientDependency
9 | {
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundEventArgsBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.Identity;
5 |
6 | namespace Xpress.Core.BackgroundJobs
7 | {
8 | public class BackgroundEventArgsBase : IBackgroundEventArgs
9 | {
10 | ///
11 | /// 事件Id
12 | ///
13 | public string EventId { get; set; } = GuidProvider.Comb.Create().ToString("N");
14 |
15 | ///
16 | /// 事件发布时间
17 | ///
18 | public DateTime EventTime { get; set; } = DateTime.Now;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundJobArgsHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.Exceptions;
5 |
6 | namespace Xpress.Core.BackgroundJobs
7 | {
8 | public static class BackgroundJobArgsHelper
9 | {
10 | public static Type GetJobArgsType(Type jobType)
11 | {
12 | foreach (var @interface in jobType.GetInterfaces())
13 | {
14 | if (!@interface.IsGenericType)
15 | {
16 | continue;
17 | }
18 |
19 | if (@interface.GetGenericTypeDefinition() != typeof(IBackgroundJob<>))
20 | {
21 | continue;
22 | }
23 |
24 | var genericArgs = @interface.GetGenericArguments();
25 | if (genericArgs.Length != 1)
26 | {
27 | continue;
28 | }
29 |
30 | return genericArgs[0];
31 | }
32 |
33 | throw new XpressException($"Could not find type of the job args. Ensure that given type implements the {typeof(IBackgroundJob<>).AssemblyQualifiedName} interface. Given job type: {jobType.AssemblyQualifiedName}");
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundJobConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.BackgroundJobs
6 | {
7 | public class BackgroundJobConfiguration
8 | {
9 | public Type ArgsType { get; }
10 |
11 | public Type JobType { get; }
12 |
13 | public string JobName { get; }
14 |
15 | public BackgroundJobConfiguration(Type jobType)
16 | {
17 | JobType = jobType;
18 | ArgsType = BackgroundJobArgsHelper.GetJobArgsType(jobType);
19 | JobName = BackgroundJobNameAttribute.GetName(ArgsType);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundJobExecutionException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.Serialization;
4 | using System.Text;
5 | using Xpress.Core.Exceptions;
6 |
7 | namespace Xpress.Core.BackgroundJobs
8 | {
9 | [Serializable]
10 | public class BackgroundJobExecutionException : XpressException
11 | {
12 | public string JobType { get; set; }
13 |
14 | public object JobArgs { get; set; }
15 |
16 | public BackgroundJobExecutionException()
17 | {
18 |
19 | }
20 |
21 | ///
22 | /// Creates a new object.
23 | ///
24 | public BackgroundJobExecutionException(SerializationInfo serializationInfo, StreamingContext context)
25 | : base(serializationInfo, context)
26 | {
27 |
28 | }
29 |
30 | ///
31 | /// Creates a new object.
32 | ///
33 | /// Exception message
34 | /// Inner exception
35 | public BackgroundJobExecutionException(string message, Exception innerException)
36 | : base(message, innerException)
37 | {
38 |
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundJobManagerExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.Threading;
5 | using Xpress.Core.Utils;
6 |
7 | namespace Xpress.Core.BackgroundJobs
8 | {
9 | ///
10 | /// Some extension methods for .
11 | ///
12 | public static class BackgroundJobManagerExtensions
13 | {
14 | ///
15 | /// Enqueues a job to be executed.
16 | ///
17 | /// Type of the arguments of job.
18 | /// Background job manager reference
19 | /// Job arguments.
20 | /// Job priority.
21 | /// Job delay (wait duration before first try).
22 | public static string Enqueue(this IBackgroundJobManager backgroundJobManager, TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null)
23 | where TArgs : IBackgroundEventArgs
24 | {
25 | return AsyncHelper.RunSync(() => backgroundJobManager.EnqueueAsync(args, priority, delay));
26 | }
27 |
28 | ///
29 | /// Checks if background job system has a real implementation.
30 | /// It returns false if the current implementation is .
31 | ///
32 | ///
33 | ///
34 | public static bool IsAvailable(this IBackgroundJobManager backgroundJobManager)
35 | {
36 | return !(CastleProxyHelper.UnProxy(backgroundJobManager) is NullBackgroundJobManager);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundJobNameAttribute.cs:
--------------------------------------------------------------------------------
1 | using Hangfire.Annotations;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using Xpress.Core.Utils;
7 |
8 | namespace Xpress.Core.BackgroundJobs
9 | {
10 | public class BackgroundJobNameAttribute : Attribute, IBackgroundJobNameProvider
11 | {
12 | public string Name { get; }
13 |
14 | public BackgroundJobNameAttribute([NotNull] string name)
15 | {
16 | Name = Check.NotNullOrWhiteSpace(name, nameof(name));
17 | }
18 |
19 | public static string GetName() where TArgs : IBackgroundEventArgs
20 | {
21 | return GetName(typeof(TArgs));
22 | }
23 |
24 | public static string GetName([NotNull] Type jobArgsType)
25 | {
26 | Check.NotNull(jobArgsType, nameof(jobArgsType));
27 |
28 | return jobArgsType
29 | .GetCustomAttributes(true)
30 | .OfType()
31 | .FirstOrDefault()
32 | ?.Name
33 | ?? jobArgsType.FullName;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/BackgroundJobPriority.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.BackgroundJobs
6 | {
7 | ///
8 | /// Priority of a background job.
9 | ///
10 | public enum BackgroundJobPriority : byte
11 | {
12 | ///
13 | /// Low.
14 | ///
15 | Low = 5,
16 |
17 | ///
18 | /// Below normal.
19 | ///
20 | BelowNormal = 10,
21 |
22 | ///
23 | /// Normal (default).
24 | ///
25 | Normal = 15,
26 |
27 | ///
28 | /// Above normal.
29 | ///
30 | AboveNormal = 20,
31 |
32 | ///
33 | /// High.
34 | ///
35 | High = 25
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/HangfireBackgroundJobManager.cs:
--------------------------------------------------------------------------------
1 | using Hangfire;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Xpress.Core.DependencyInjection;
7 |
8 | namespace Xpress.Core.BackgroundJobs
9 | {
10 | public class HangfireBackgroundJobManager : IBackgroundJobManager, ISingletonDependency
11 | {
12 | public Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null)
13 | where TArgs : IBackgroundEventArgs
14 | {
15 | if (!delay.HasValue)
16 | {
17 | return Task.FromResult(
18 | BackgroundJob.Enqueue>(adapter => adapter.Execute(args))
19 | );
20 | }
21 | else
22 | {
23 | return Task.FromResult(
24 | BackgroundJob.Schedule>(adapter => adapter.Execute(args), delay.Value)
25 | );
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/HangfireJobExecutionAdapter.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Options;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 |
7 | namespace Xpress.Core.BackgroundJobs
8 | {
9 | public class HangfireJobExecutionAdapter where TArgs : IBackgroundEventArgs
10 | {
11 | protected BackgroundJobOptions Options { get; }
12 | protected IServiceScopeFactory ServiceScopeFactory { get; }
13 | protected IBackgroundJobExecuter JobExecuter { get; }
14 |
15 | public HangfireJobExecutionAdapter(IOptions options,
16 | IBackgroundJobExecuter jobExecuter, IServiceScopeFactory serviceScopeFactory)
17 | {
18 | JobExecuter = jobExecuter;
19 | ServiceScopeFactory = serviceScopeFactory;
20 | Options = options.Value;
21 | }
22 |
23 | public void Execute(TArgs args)
24 | {
25 | using (var scope = ServiceScopeFactory.CreateScope())
26 | {
27 | var jobType = Options.GetJob(typeof(TArgs)).JobType;
28 | var context = new JobExecutionContext(scope.ServiceProvider, jobType, args);
29 | JobExecuter.Execute(context);
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/IBackgroundEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.BackgroundJobs
6 | {
7 | public interface IBackgroundEventArgs
8 | {
9 | ///
10 | /// 事件Id
11 | ///
12 | string EventId { get; set; }
13 |
14 | ///
15 | /// 事件发布时间
16 | ///
17 | DateTime EventTime { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/IBackgroundJob.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.BackgroundJobs
6 | {
7 | public interface IBackgroundJob
8 | { }
9 |
10 | ///
11 | /// Defines interface of a background job.
12 | ///
13 | public interface IBackgroundJob: IBackgroundJob where TArgs : IBackgroundEventArgs
14 | {
15 | ///
16 | /// Executes the job with the .
17 | ///
18 | /// Job arguments.
19 | void Execute(TArgs args);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/IBackgroundJobExecuter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.BackgroundJobs
6 | {
7 | public interface IBackgroundJobExecuter
8 | {
9 | void Execute(JobExecutionContext context);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/IBackgroundJobManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 |
6 | namespace Xpress.Core.BackgroundJobs
7 | {
8 | ///
9 | /// Defines interface of a job manager.
10 | ///
11 | public interface IBackgroundJobManager
12 | {
13 | ///
14 | /// Enqueues a job to be executed.
15 | ///
16 | /// Type of the arguments of job.
17 | /// Job arguments.
18 | /// Job priority.
19 | /// Job delay (wait duration before first try).
20 | /// Unique identifier of a background job.
21 | Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) where TArgs : IBackgroundEventArgs;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/IBackgroundJobNameProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.BackgroundJobs
6 | {
7 | public interface IBackgroundJobNameProvider
8 | {
9 | string Name { get; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/JobExecutionContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xpress.Core.DependencyInjection;
5 |
6 | namespace Xpress.Core.BackgroundJobs
7 | {
8 | public class JobExecutionContext : IServiceProviderAccessor
9 | {
10 | public IServiceProvider ServiceProvider { get; }
11 |
12 | public Type JobType { get; }
13 |
14 | public object JobArgs { get; }
15 |
16 | public JobExecutionContext(IServiceProvider serviceProvider, Type jobType, object jobArgs)
17 | {
18 | ServiceProvider = serviceProvider;
19 | JobType = jobType;
20 | JobArgs = jobArgs;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/BackgroundJobs/NullBackgroundJobManager.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Microsoft.Extensions.Logging.Abstractions;
3 | using System;
4 | using System.Threading.Tasks;
5 | using Xpress.Core.DependencyInjection;
6 |
7 | namespace Xpress.Core.BackgroundJobs
8 | {
9 | public class NullBackgroundJobManager : IBackgroundJobManager
10 | {
11 | public ILogger Logger { get; set; }
12 |
13 | public static NullBackgroundJobManager Instance => new NullBackgroundJobManager();
14 |
15 | public NullBackgroundJobManager()
16 | {
17 | Logger = NullLogger.Instance;
18 | }
19 |
20 | public virtual async Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null)
21 | where TArgs : IBackgroundEventArgs
22 | {
23 | Logger.LogInformation("Background job system has not a real implementation. If it's mandatory, use an implementation (either the default provider or a 3rd party implementation). If it's optional, check IBackgroundJobManager.IsAvailable() extension method and act based on it.");
24 |
25 | return await Task.FromResult(string.Empty);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/Caching/CacheNameAttribute.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Annotations;
2 | using System;
3 | using Xpress.Core.Utils;
4 |
5 | namespace Xpress.Core.Caching
6 | {
7 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct)]
8 | public class CacheNameAttribute : Attribute
9 | {
10 | public string Name { get; }
11 |
12 | public CacheNameAttribute([NotNull] string name)
13 | {
14 | Check.NotNull(name, nameof(name));
15 |
16 | Name = name;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/Caching/IDistributedCache.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Annotations;
2 | using Microsoft.Extensions.Caching.Distributed;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace Xpress.Core.Caching
10 | {
11 | public interface IDistributedCache
12 | where TCacheItem : class
13 | {
14 | TCacheItem Get(string key);
15 |
16 | Task GetAsync([NotNull] string key, CancellationToken token = default(CancellationToken));
17 |
18 | TCacheItem GetOrAdd(string key, Func factory, Func optionsFactory = null);
19 |
20 | Task GetOrAddAsync(
21 | [NotNull] string key,
22 | Func> factory,
23 | Func optionsFactory = null,
24 | CancellationToken token = default(CancellationToken)
25 | );
26 |
27 | void Set(string key, TCacheItem value, DistributedCacheEntryOptions options = null);
28 |
29 | Task SetAsync(
30 | [NotNull] string key,
31 | [NotNull] TCacheItem value,
32 | [CanBeNull] DistributedCacheEntryOptions options = null,
33 | CancellationToken token = default(CancellationToken)
34 | );
35 |
36 | void Refresh(string key);
37 |
38 | Task RefreshAsync(string key, CancellationToken token = default(CancellationToken));
39 |
40 | void Remove(string key);
41 |
42 | Task RemoveAsync(string key, CancellationToken token = default(CancellationToken));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Source/Xpress.Core/Collections/ITypeList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Xpress.Core.Collections
6 | {
7 | ///
8 | /// A shortcut for to use object as base type.
9 | ///
10 | public interface ITypeList : ITypeList