26 changed files with 555 additions and 51 deletions
@ -1,7 +1,33 @@ |
|||||
using Volo.Abp.Modularity; |
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
namespace LINGYUN.Abp.BackgroundTasks; |
namespace LINGYUN.Abp.BackgroundTasks; |
||||
|
|
||||
public class AbpBackgroundTasksAbstractionsModule : AbpModule |
public class AbpBackgroundTasksAbstractionsModule : AbpModule |
||||
{ |
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
AutoAddJobMonitors(context.Services); |
||||
|
} |
||||
|
|
||||
|
private static void AutoAddJobMonitors(IServiceCollection services) |
||||
|
{ |
||||
|
var jobMonitors = new List<Type>(); |
||||
|
|
||||
|
services.OnRegistred(context => |
||||
|
{ |
||||
|
if (ReflectionHelper.IsAssignableToGenericType(context.ImplementationType, typeof(JobEventBase<>))) |
||||
|
{ |
||||
|
jobMonitors.Add(context.ImplementationType); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
services.Configure<AbpBackgroundTasksOptions>(options => |
||||
|
{ |
||||
|
options.JobMonitors.AddIfNotContains(jobMonitors); |
||||
|
}); |
||||
|
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,44 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks; |
||||
|
|
||||
|
public class AbpJobExecutionException : AbpException |
||||
|
{ |
||||
|
public Type JobType { get; } |
||||
|
/// <summary>
|
||||
|
/// Creates a new <see cref="AbpJobExecutionException"/> object.
|
||||
|
/// </summary>
|
||||
|
/// <param name="innerException">Inner exception</param>
|
||||
|
public AbpJobExecutionException(Type jobType) |
||||
|
: this( |
||||
|
jobType, |
||||
|
$"Unable to execute job {jobType.Name}.", |
||||
|
null) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new <see cref="AbpJobExecutionException"/> object.
|
||||
|
/// </summary>
|
||||
|
/// <param name="jobType">Execute job type</param>
|
||||
|
/// <param name="innerException">Inner exception</param>
|
||||
|
public AbpJobExecutionException(Type jobType, Exception innerException) |
||||
|
: this( |
||||
|
jobType, |
||||
|
$"Unable to execute job {jobType.Name} because it: {innerException.Message}", |
||||
|
innerException) |
||||
|
{ |
||||
|
} |
||||
|
/// <summary>
|
||||
|
/// Creates a new <see cref="AbpJobExecutionException"/> object.
|
||||
|
/// </summary>
|
||||
|
/// <param name="jobType">Execute job type</param>
|
||||
|
/// <param name="message">Exception message</param>
|
||||
|
/// <param name="innerException">Inner exception</param>
|
||||
|
public AbpJobExecutionException(Type jobType, string message, Exception innerException) |
||||
|
: base(message, innerException) |
||||
|
{ |
||||
|
JobType = jobType; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks; |
||||
|
|
||||
|
public static class JobRunnableContextExtensions |
||||
|
{ |
||||
|
public static T GetService<T>(this JobRunnableContext context) |
||||
|
{ |
||||
|
return context.ServiceProvider.GetService<T>(); |
||||
|
} |
||||
|
|
||||
|
public static object GetService(this JobRunnableContext context, Type serviceType) |
||||
|
{ |
||||
|
return context.ServiceProvider.GetService(serviceType); |
||||
|
} |
||||
|
|
||||
|
public static T GetRequiredService<T>(this JobRunnableContext context) |
||||
|
{ |
||||
|
return context.ServiceProvider.GetRequiredService<T>(); |
||||
|
} |
||||
|
|
||||
|
public static object GetRequiredService(this JobRunnableContext context, Type serviceType) |
||||
|
{ |
||||
|
return context.ServiceProvider.GetRequiredService(serviceType); |
||||
|
} |
||||
|
|
||||
|
public static string GetString(this JobRunnableContext context, string key) |
||||
|
{ |
||||
|
return context.GetJobData(key).ToString(); |
||||
|
} |
||||
|
|
||||
|
public static bool TryGetString(this JobRunnableContext context, string key, out string value) |
||||
|
{ |
||||
|
if (context.TryGetJobData(key, out var data) && data != null) |
||||
|
{ |
||||
|
value = data.ToString(); |
||||
|
return true; |
||||
|
} |
||||
|
value = default; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
public static T GetJobData<T>(this JobRunnableContext context, string key) where T : struct |
||||
|
{ |
||||
|
var value = context.GetJobData(key); |
||||
|
|
||||
|
return value.To<T>(); |
||||
|
} |
||||
|
|
||||
|
public static bool TryGetJobData<T>(this JobRunnableContext context, string key, out T value) where T : struct |
||||
|
{ |
||||
|
if (context.TryGetJobData(key, out var data) && data != null) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
value = data.To<T>(); |
||||
|
return true; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
value = default; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
public static object GetJobData(this JobRunnableContext context, string key) |
||||
|
{ |
||||
|
if (context.TryGetJobData(key, out var value) && value != null) |
||||
|
{ |
||||
|
return value; |
||||
|
} |
||||
|
throw new ArgumentException(key + " not specified."); |
||||
|
} |
||||
|
|
||||
|
public static bool TryGetJobData(this JobRunnableContext context, string key, out object value) |
||||
|
{ |
||||
|
if (context.JobData.TryGetValue(key, out value)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,21 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Emailing" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Sms" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Http.Client" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.BackgroundTasks.Abstractions\LINGYUN.Abp.BackgroundTasks.Abstractions.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,25 @@ |
|||||
|
using Volo.Abp.Emailing; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Sms; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
|
[DependsOn(typeof(AbpEmailingModule))] |
||||
|
[DependsOn(typeof(AbpSmsModule))] |
||||
|
[DependsOn(typeof(AbpHttpClientModule))] |
||||
|
public class AbpBackgroundTasksJobsModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpBackgroundTasksOptions>(options => |
||||
|
{ |
||||
|
options.AddProvider<ConsoleJob>(DefaultJobNames.ConsoleJob); |
||||
|
options.AddProvider<SendEmailJob>(DefaultJobNames.SendEmailJob); |
||||
|
options.AddProvider<SendSmsJob>(DefaultJobNames.SendSmsJob); |
||||
|
options.AddProvider<SleepJob>(DefaultJobNames.SleepJob); |
||||
|
options.AddProvider<ServiceInvocationJob>(DefaultJobNames.ServiceInvocationJob); |
||||
|
options.AddProvider<HttpRequestJob>(DefaultJobNames.HttpRequestJob); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,7 @@ |
|||||
using System; |
using System; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
namespace LINGYUN.Abp.BackgroundTasks.Primitives; |
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
public class ConsoleJob : IJobRunnable |
public class ConsoleJob : IJobRunnable |
||||
{ |
{ |
||||
@ -0,0 +1,29 @@ |
|||||
|
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
|
public static class DefaultJobNames |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 发送邮件
|
||||
|
/// </summary>
|
||||
|
public const string SendEmailJob = "SendEmail"; |
||||
|
/// <summary>
|
||||
|
/// 发送短信
|
||||
|
/// </summary>
|
||||
|
public const string SendSmsJob = "SendSms"; |
||||
|
/// <summary>
|
||||
|
/// 控制台输出
|
||||
|
/// </summary>
|
||||
|
public const string ConsoleJob = "Console"; |
||||
|
/// <summary>
|
||||
|
/// 休眠
|
||||
|
/// </summary>
|
||||
|
public const string SleepJob = "Sleep"; |
||||
|
/// <summary>
|
||||
|
/// 服务间调用
|
||||
|
/// </summary>
|
||||
|
public const string ServiceInvocationJob = "ServiceInvocation"; |
||||
|
/// <summary>
|
||||
|
/// Http请求
|
||||
|
/// </summary>
|
||||
|
public const string HttpRequestJob = "HttpRequest"; |
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Net.Http; |
||||
|
using System.Net.Http.Headers; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Http; |
||||
|
using Volo.Abp.Json; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
|
public class HttpRequestJob : IJobRunnable |
||||
|
{ |
||||
|
public const string PropertyUrl = "url"; |
||||
|
public const string PropertyMethod = "method"; |
||||
|
public const string PropertyData = "data"; |
||||
|
public const string PropertyContentType = "contentType"; |
||||
|
public const string PropertyHeaders = "headers"; |
||||
|
public const string PropertyToken = "token"; |
||||
|
|
||||
|
public virtual async Task ExecuteAsync(JobRunnableContext context) |
||||
|
{ |
||||
|
var clientFactory = context.GetRequiredService<IHttpClientFactory>(); |
||||
|
|
||||
|
var client = clientFactory.CreateClient(); |
||||
|
var requestMessage = BuildRequestMessage(context); |
||||
|
|
||||
|
var response = await client.SendAsync( |
||||
|
requestMessage, |
||||
|
HttpCompletionOption.ResponseHeadersRead); |
||||
|
|
||||
|
var stringContent = await response.Content.ReadAsStringAsync(); |
||||
|
|
||||
|
if (!response.IsSuccessStatusCode && stringContent.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
context.SetResult($"HttpStatusCode: {(int)response.StatusCode}, Reason: {response.ReasonPhrase}"); |
||||
|
return; |
||||
|
} |
||||
|
context.SetResult(stringContent); |
||||
|
} |
||||
|
|
||||
|
protected virtual HttpRequestMessage BuildRequestMessage(JobRunnableContext context) |
||||
|
{ |
||||
|
var url = context.GetString(PropertyUrl); |
||||
|
var method = context.GetString(PropertyMethod); |
||||
|
context.TryGetJobData(PropertyData, out var data); |
||||
|
context.TryGetJobData(PropertyContentType, out var contentType); |
||||
|
|
||||
|
var jsonSerializer = context.GetRequiredService<IJsonSerializer>(); |
||||
|
|
||||
|
var httpRequestMesasge = new HttpRequestMessage(new HttpMethod(method), url); |
||||
|
if (data != null) |
||||
|
{ |
||||
|
// TODO: 需要支持表单类型
|
||||
|
|
||||
|
// application/json 支持
|
||||
|
httpRequestMesasge.Content = new StringContent( |
||||
|
jsonSerializer.Serialize(data), |
||||
|
Encoding.UTF8, |
||||
|
contentType?.ToString() ?? MimeTypes.Application.Json); |
||||
|
} |
||||
|
if (context.TryGetJobData(PropertyHeaders, out var headers) && |
||||
|
headers is IDictionary<string, string> headersDic) |
||||
|
{ |
||||
|
foreach (var header in headersDic) |
||||
|
{ |
||||
|
httpRequestMesasge.Headers.Add(header.Key, header.Value); |
||||
|
} |
||||
|
} |
||||
|
// TODO: 和 headers 一起?
|
||||
|
if (context.TryGetString(PropertyToken, out var accessToken)) |
||||
|
{ |
||||
|
httpRequestMesasge.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); |
||||
|
} |
||||
|
|
||||
|
return httpRequestMesasge; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Emailing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
|
public class SendEmailJob : IJobRunnable |
||||
|
{ |
||||
|
public const string PropertyFrom = "from"; |
||||
|
public const string PropertyTo = "to"; |
||||
|
public const string PropertySubject = "subject"; |
||||
|
public const string PropertyBody = "body"; |
||||
|
public const string PropertyIsBodyHtml = "isBodyHtml"; |
||||
|
|
||||
|
public virtual async Task ExecuteAsync(JobRunnableContext context) |
||||
|
{ |
||||
|
context.TryGetString(PropertyFrom, out var from); |
||||
|
var to = context.GetString(PropertyTo); |
||||
|
var subject = context.GetString(PropertySubject); |
||||
|
var body = context.GetString(PropertyBody); |
||||
|
context.TryGetJobData<bool>(PropertyIsBodyHtml, out var isBodyHtml); |
||||
|
|
||||
|
var emailSender = context.GetRequiredService<IEmailSender>(); |
||||
|
|
||||
|
await emailSender.QueueAsync(from, to, subject, body, isBodyHtml); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Sms; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
|
public class SendSmsJob : IJobRunnable |
||||
|
{ |
||||
|
public const string PropertyPhoneNumber = "phoneNumber"; |
||||
|
public const string PropertyMessage = "message"; |
||||
|
public const string PropertyProperties = "properties"; |
||||
|
|
||||
|
public virtual async Task ExecuteAsync(JobRunnableContext context) |
||||
|
{ |
||||
|
var phoneNumber = context.GetString(PropertyPhoneNumber); |
||||
|
var message = context.GetString(PropertyMessage); |
||||
|
|
||||
|
var smsMessage = new SmsMessage(phoneNumber, message); |
||||
|
if (context.TryGetJobData(PropertyProperties, out var data) && |
||||
|
data is IDictionary<string, object> properties) |
||||
|
{ |
||||
|
smsMessage.Properties.AddIfNotContains(properties); |
||||
|
} |
||||
|
|
||||
|
var smsSender = context.GetRequiredService<ISmsSender>(); |
||||
|
|
||||
|
await smsSender.SendAsync(smsMessage); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,117 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Http.Client.ClientProxying; |
||||
|
using Volo.Abp.Http.Client.DynamicProxying; |
||||
|
using Volo.Abp.Http.Client.Proxying; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
|
public class ServiceInvocationJob : IJobRunnable |
||||
|
{ |
||||
|
public const string PropertyService = "service"; |
||||
|
public const string PropertyMethod = "method"; |
||||
|
public const string PropertyCulture = "culture"; |
||||
|
|
||||
|
public virtual async Task ExecuteAsync(JobRunnableContext context) |
||||
|
{ |
||||
|
// 获取参数列表
|
||||
|
var type = context.GetString(PropertyService); |
||||
|
var method = context.GetString(PropertyMethod); |
||||
|
var serviceType = Type.GetType(type, true); |
||||
|
var serviceMethod = serviceType.GetMethod(method); |
||||
|
context.TryGetString(PropertyCulture, out var culture); |
||||
|
|
||||
|
using (CultureHelper.Use(culture ?? CultureInfo.CurrentCulture.Name)) |
||||
|
{ |
||||
|
// 反射所必须的参数
|
||||
|
var callRequestMethod = nameof(DynamicHttpProxyInterceptorClientProxy<object>.CallRequestAsync); |
||||
|
var clientProxyType = typeof(DynamicHttpProxyInterceptorClientProxy<>).MakeGenericType(serviceType); |
||||
|
var clientProxy = context.GetRequiredService(clientProxyType); |
||||
|
var clientProxyMethod = typeof(DynamicHttpProxyInterceptorClientProxy<>).GetMethod(callRequestMethod); |
||||
|
|
||||
|
// 调用远程服务发现端点
|
||||
|
var actionApiDescription = await GetActionApiDescriptionModel(context, serviceType, serviceMethod); |
||||
|
|
||||
|
// 拼接调用参数
|
||||
|
var invokeParameters = new Dictionary<string, object>(); |
||||
|
var methodParameters = serviceMethod.GetParameters(); |
||||
|
foreach (var parameter in methodParameters) |
||||
|
{ |
||||
|
if (context.TryGetJobData(parameter.Name, out var value)) |
||||
|
{ |
||||
|
invokeParameters.Add(parameter.Name, value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 构造服务代理上下文
|
||||
|
var clientProxyRequestContext = new ClientProxyRequestContext( |
||||
|
actionApiDescription, |
||||
|
invokeParameters, |
||||
|
serviceType); |
||||
|
|
||||
|
if (serviceMethod.ReturnType.GenericTypeArguments.IsNullOrEmpty()) |
||||
|
{ |
||||
|
// 直接调用
|
||||
|
var taskProxy = (Task)clientProxyMethod.Invoke(clientProxy, new object[] { clientProxyRequestContext }); |
||||
|
await taskProxy; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
// 有返回值的调用
|
||||
|
|
||||
|
var callRequestAsyncMethod = typeof(DynamicHttpProxyInterceptor<object>) |
||||
|
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance) |
||||
|
.First(m => m.Name == callRequestMethod && m.IsGenericMethodDefinition); |
||||
|
|
||||
|
var returnType = serviceMethod.ReturnType.GenericTypeArguments[0]; |
||||
|
var result = (Task)callRequestAsyncMethod |
||||
|
.MakeGenericMethod(returnType) |
||||
|
.Invoke(this, new object[] { context }); |
||||
|
|
||||
|
context.SetResult(await GetResultAsync(result, returnType)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<ActionApiDescriptionModel> GetActionApiDescriptionModel( |
||||
|
JobRunnableContext context, |
||||
|
Type serviceType, |
||||
|
MethodInfo method) |
||||
|
{ |
||||
|
var clientOptions = context.GetRequiredService<IOptions<AbpHttpClientOptions>>().Value; |
||||
|
var remoteServiceConfigurationProvider = context.GetRequiredService<IRemoteServiceConfigurationProvider>(); |
||||
|
var proxyHttpClientFactory = context.GetRequiredService<IProxyHttpClientFactory>(); |
||||
|
var apiDescriptionFinder = context.GetRequiredService<IApiDescriptionFinder>(); |
||||
|
|
||||
|
var clientConfig = clientOptions.HttpClientProxies.GetOrDefault(serviceType) ?? |
||||
|
throw new AbpException($"Could not get DynamicHttpClientProxyConfig for {serviceType.FullName}."); |
||||
|
var remoteServiceConfig = await remoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(clientConfig.RemoteServiceName); |
||||
|
var client = proxyHttpClientFactory.Create(clientConfig.RemoteServiceName); |
||||
|
|
||||
|
return await apiDescriptionFinder.FindActionAsync( |
||||
|
client, |
||||
|
remoteServiceConfig.BaseUrl, |
||||
|
serviceType, |
||||
|
method |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<object> GetResultAsync(Task task, Type resultType) |
||||
|
{ |
||||
|
await task; |
||||
|
var resultProperty = typeof(Task<>) |
||||
|
.MakeGenericType(resultType) |
||||
|
.GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public); |
||||
|
Check.NotNull(resultProperty, nameof(resultProperty)); |
||||
|
return resultProperty.GetValue(task); |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,7 @@ |
|||||
using System; |
using System; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
namespace LINGYUN.Abp.BackgroundTasks.Primitives; |
namespace LINGYUN.Abp.BackgroundTasks.Jobs; |
||||
|
|
||||
public class SleepJob : IJobRunnable |
public class SleepJob : IJobRunnable |
||||
{ |
{ |
||||
@ -1,14 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace LINGYUN.Abp.BackgroundTasks.Primitives; |
|
||||
|
|
||||
public class EmailingJob : IJobRunnable |
|
||||
{ |
|
||||
public virtual async Task ExecuteAsync(JobRunnableContext context) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue