允许在Scoped环境里执行Job

pull/19/head
彭伟 4 years ago
parent 63b46caeea
commit 8621784ba1
  1. 7
      src/DotXxlJob.Core/DefaultJobHandlerFactory.cs
  2. 44
      src/DotXxlJob.Core/Extensions/ServiceCollectionExtensions.cs
  3. 27
      src/DotXxlJob.Core/JobHandlerCache.cs
  4. 8
      tests/DotXxlJob.Core.Tests/BeanTaskExecutorTest.cs

@ -1,10 +1,9 @@
using System; using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace DotXxlJob.Core namespace DotXxlJob.Core
{ {
public class DefaultJobHandlerFactory : IJobHandlerFactory public class DefaultJobHandlerFactory : IJobHandlerFactory
{ {
private readonly JobHandlerCache _handlerCache; private readonly JobHandlerCache _handlerCache;
@ -22,7 +21,7 @@ namespace DotXxlJob.Core
_handlerCache.AddJobHandler(handler); _handlerCache.AddJobHandler(handler);
} }
if (_handlerCache.HandlersCache.Count < 1) if (_handlerCache.IsEmpty)
{ {
throw new TypeLoadException("IJobHandlers are not found in IServiceCollection"); throw new TypeLoadException("IJobHandlers are not found in IServiceCollection");
} }
@ -40,7 +39,7 @@ namespace DotXxlJob.Core
serviceScope = scopeFactory.CreateScope(); serviceScope = scopeFactory.CreateScope();
return (IJobHandler)ActivatorUtilities.CreateInstance(serviceScope.ServiceProvider, jobHandler.JobHandlerType, jobHandler.JobHandlerConstructorParameters); return (IJobHandler)serviceScope.ServiceProvider.GetRequiredService(jobHandler.JobHandlerType);
} }
} }
} }

@ -56,33 +56,45 @@ namespace DotXxlJob.Core
} }
/// <summary>允许创建Scoped实例</summary> /// <summary>允许创建Scoped实例</summary>
/// <typeparam name="TJob"></typeparam> public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services)
/// <param name="services"></param> where TJob : class, IJobHandler
/// <param name="constructorParameters">用于创建实例的额外参数,比如字符串</param> {
/// <returns></returns> services.GetJobHandlerCache().AddJobHandler<TJob>();
return services.AddScoped<TJob>();
}
/// <summary>允许创建Scoped实例</summary>
public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services, public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services,
params object[] constructorParameters) where TJob : IJobHandler Func<IServiceProvider, TJob> implementationFactory)
where TJob : class, IJobHandler
{ {
services.GetJobHandlerCache().AddJobHandler<TJob>(constructorParameters); services.GetJobHandlerCache().AddJobHandler<TJob>();
return services; return services.AddScoped(implementationFactory);
} }
/// <summary>允许创建Scoped实例</summary> /// <summary>允许创建Scoped实例</summary>
/// <typeparam name="TJob"></typeparam>
/// <param name="services"></param>
/// <param name="handlerName"></param>
/// <param name="constructorParameters">用于创建实例的额外参数,比如字符串</param>
/// <returns></returns>
public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services, public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services,
string handlerName, params object[] constructorParameters) where TJob : IJobHandler string handlerName)
where TJob : class, IJobHandler
{ {
services.GetJobHandlerCache().AddJobHandler<TJob>(handlerName, constructorParameters); services.GetJobHandlerCache().AddJobHandler<TJob>(handlerName);
return services; return services.AddScoped<TJob>();
}
/// <summary>允许创建Scoped实例</summary>
public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services,
string handlerName, Func<IServiceProvider, TJob> implementationFactory)
where TJob : class, IJobHandler
{
services.GetJobHandlerCache().AddJobHandler<TJob>(handlerName);
return services.AddScoped(implementationFactory);
} }
private static JobHandlerCache GetJobHandlerCache(this IServiceCollection services) private static JobHandlerCache GetJobHandlerCache(this IServiceCollection services)
{ {
var sd = services.FirstOrDefault(x => x.ImplementationInstance is JobHandlerCache); var sd = services.FirstOrDefault(x => x.ImplementationInstance is JobHandlerCache);
if (sd != null) return (JobHandlerCache)sd.ImplementationInstance; if (sd != null) return (JobHandlerCache)sd.ImplementationInstance;

@ -1,26 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using DotXxlJob.Core.DefaultHandlers;
namespace DotXxlJob.Core namespace DotXxlJob.Core
{ {
public class JobHandlerCache public class JobHandlerCache
{ {
internal Dictionary<string, JobHandlerItem> HandlersCache { get; } = new Dictionary<string, JobHandlerItem>(); private readonly Dictionary<string, JobHandlerItem> _handlersCache = new Dictionary<string, JobHandlerItem>();
public void AddJobHandler<TJob>(params object[] constructorParameters) public bool IsEmpty => _handlersCache.Count < 1;
where TJob : IJobHandler =>
public void AddJobHandler<TJob>() where TJob : IJobHandler =>
AddJobHandler<TJob>(typeof(TJob).GetCustomAttribute<JobHandlerAttribute>()?.Name ?? AddJobHandler<TJob>(typeof(TJob).GetCustomAttribute<JobHandlerAttribute>()?.Name ??
typeof(TJob).Name, constructorParameters); typeof(TJob).Name);
public void AddJobHandler<TJob>(string handlerName, params object[] constructorParameters) public void AddJobHandler<TJob>(string handlerName) where TJob : IJobHandler =>
where TJob : IJobHandler => AddJobHandler(handlerName, new JobHandlerItem { JobHandlerType = typeof(TJob) });
AddJobHandler(handlerName, new JobHandlerItem {
JobHandlerType = typeof(TJob),
JobHandlerConstructorParameters = constructorParameters,
});
public void AddJobHandler(IJobHandler jobHandler) public void AddJobHandler(IJobHandler jobHandler)
{ {
@ -39,24 +34,22 @@ namespace DotXxlJob.Core
private void AddJobHandler(string handlerName, JobHandlerItem jobHandler) private void AddJobHandler(string handlerName, JobHandlerItem jobHandler)
{ {
if (HandlersCache.ContainsKey(handlerName)) if (_handlersCache.ContainsKey(handlerName))
{ {
throw new ArgumentException($"Same IJobHandler' name: [{handlerName}]", nameof(handlerName)); throw new ArgumentException($"Same IJobHandler' name: [{handlerName}]", nameof(handlerName));
} }
HandlersCache.Add(handlerName, jobHandler); _handlersCache.Add(handlerName, jobHandler);
} }
public JobHandlerItem Get(string handlerName) => public JobHandlerItem Get(string handlerName) =>
HandlersCache.TryGetValue(handlerName, out var item) ? item : null; _handlersCache.TryGetValue(handlerName, out var item) ? item : null;
public class JobHandlerItem public class JobHandlerItem
{ {
public IJobHandler JobHandler { get; set; } public IJobHandler JobHandler { get; set; }
public Type JobHandlerType { get; set; } public Type JobHandlerType { get; set; }
public object[] JobHandlerConstructorParameters { get; set; }
} }
} }
} }

@ -1,14 +1,12 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using DotXxlJob.Core.DefaultHandlers;
using DotXxlJob.Core.Model; using DotXxlJob.Core.Model;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Xunit; using Xunit;
namespace DotXxlJob.Core.Tests namespace DotXxlJob.Core.Tests
{ {
public class BeanTaskExecutorTest public class BeanTaskExecutorTest
{ {
[Fact] [Fact]
public async Task Repeated_Job_Handler() public async Task Repeated_Job_Handler()
@ -21,7 +19,7 @@ namespace DotXxlJob.Core.Tests
var list = new List<object>(); var list = new List<object>();
services.AddJobHandler<TestJobHandler>("test", list); services.AddJobHandler<TestJobHandler>("test", x => ActivatorUtilities.CreateInstance<TestJobHandler>(x, list));
using (var provider = services.BuildServiceProvider(true)) using (var provider = services.BuildServiceProvider(true))
{ {

Loading…
Cancel
Save