允许在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.Reflection;
using Microsoft.Extensions.DependencyInjection;
namespace DotXxlJob.Core
{
public class DefaultJobHandlerFactory : IJobHandlerFactory
public class DefaultJobHandlerFactory : IJobHandlerFactory
{
private readonly JobHandlerCache _handlerCache;
@ -22,7 +21,7 @@ namespace DotXxlJob.Core
_handlerCache.AddJobHandler(handler);
}
if (_handlerCache.HandlersCache.Count < 1)
if (_handlerCache.IsEmpty)
{
throw new TypeLoadException("IJobHandlers are not found in IServiceCollection");
}
@ -40,7 +39,7 @@ namespace DotXxlJob.Core
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>
/// <typeparam name="TJob"></typeparam>
/// <param name="services"></param>
/// <param name="constructorParameters">用于创建实例的额外参数,比如字符串</param>
/// <returns></returns>
public static IServiceCollection AddJobHandler<TJob>(this IServiceCollection services)
where TJob : class, IJobHandler
{
services.GetJobHandlerCache().AddJobHandler<TJob>();
return services.AddScoped<TJob>();
}
/// <summary>允许创建Scoped实例</summary>
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>
/// <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,
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);
if (sd != null) return (JobHandlerCache)sd.ImplementationInstance;

@ -1,26 +1,21 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using DotXxlJob.Core.DefaultHandlers;
namespace DotXxlJob.Core
{
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)
where TJob : IJobHandler =>
public bool IsEmpty => _handlersCache.Count < 1;
public void AddJobHandler<TJob>() where TJob : IJobHandler =>
AddJobHandler<TJob>(typeof(TJob).GetCustomAttribute<JobHandlerAttribute>()?.Name ??
typeof(TJob).Name, constructorParameters);
typeof(TJob).Name);
public void AddJobHandler<TJob>(string handlerName, params object[] constructorParameters)
where TJob : IJobHandler =>
AddJobHandler(handlerName, new JobHandlerItem {
JobHandlerType = typeof(TJob),
JobHandlerConstructorParameters = constructorParameters,
});
public void AddJobHandler<TJob>(string handlerName) where TJob : IJobHandler =>
AddJobHandler(handlerName, new JobHandlerItem { JobHandlerType = typeof(TJob) });
public void AddJobHandler(IJobHandler jobHandler)
{
@ -39,24 +34,22 @@ namespace DotXxlJob.Core
private void AddJobHandler(string handlerName, JobHandlerItem jobHandler)
{
if (HandlersCache.ContainsKey(handlerName))
if (_handlersCache.ContainsKey(handlerName))
{
throw new ArgumentException($"Same IJobHandler' name: [{handlerName}]", nameof(handlerName));
}
HandlersCache.Add(handlerName, jobHandler);
_handlersCache.Add(handlerName, jobHandler);
}
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 IJobHandler JobHandler { 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 DotXxlJob.Core.DefaultHandlers;
using DotXxlJob.Core.Model;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace DotXxlJob.Core.Tests
{
public class BeanTaskExecutorTest
public class BeanTaskExecutorTest
{
[Fact]
public async Task Repeated_Job_Handler()
@ -21,7 +19,7 @@ namespace DotXxlJob.Core.Tests
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))
{

Loading…
Cancel
Save