在策略设计模式的情况下,Hangfire服务器无法选择作业

我有以下申请:

1) Mvc应用程序 :Hangfire客户端,我将在那里排队作业和主持仪表板。这个应用程序将包含我的类库的参考。

2) 控制台应用程序 :Hangfire服务器将存在于此控制台应用程序中。

3) 类库 :hangfire服务器(控制台应用程序)和hangfire客户端(asp.net mvc)之间的共享库,我的长时间运行的代码将驻留在该库中.Hangfire服务器将执行该库的代码。

我在战略设计模式下的类库中有如下结构。

代码取自以下: 参考:

接口:

public interface IOperation { Output Process(Input input); bool AppliesTo(Type type); } public interface IOperationStrategy { Output Process(Type type,Input input); } 

操作:

 public class Add : IOperation { public bool AppliesTo(Type type) { return typeof(Add).Equals(type); } public Output Process(Input input) { // Implementation return new Output(); } } public class Multiply : IOperation { public bool AppliesTo(Type type) { return typeof(Multiply).Equals(type); } public Output Process(Input input) { // Implementation return new Output(); } } 

策略

 public class OperationStrategy : IOperationStrategy { private readonly IOperation[] operations; public OperationStrategy(params IOperation[] operations) { if (operations == null) throw new ArgumentNullException(nameof(operations)); this.operations = operations; } public Output Process(Type type, Input input) { var op = operations.FirstOrDefault(o => o.AppliesTo(type)); if (op == null) throw new InvalidOperationException($"{operation} not registered."); return op.Process(input); } } 

用法

 // Do this with your DI container in your composition // root, and the instance would be created by injecting // it somewhere. var strategy = new OperationStrategy( new Add(), // Inject any dependencies for operation here new Multiply()); // Inject any dependencies for operation here // And then once it is injected, you would simply do this. var input = new Input { Value1 = 2, Value2 = 3 }; BackgroundJob.Enqueue(() => strategy.Process(typeof(Add), input)); 

但是hangfire服务器无法选择作业,当我检查state table ,我会看到如下错误:

“FailedAt”:“2018-03-21T13:14:46.0​​172303Z”,“ExceptionType”:“System.MissingMethodException”,“ExceptionMessage”:“没有为此对象定义无参数构造函数。”,“ExceptionDetails”:“System.MissingMethodException :没有为此对象定义无参数构造函数。\ r \ n在System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,Boolean publicOnly,Boolean noCheck,Boolean&canBeCached,RuntimeMethodHandleInternal&ctor,Boolean&bNeedSecurityCheck)\ r \ n在System.RuntimeType.CreateInstanceSlow(布尔值) publicOnly,Boolean skipCheckThis,Boolean fillCache,StackCrawlMark&stackMark)\ r \ n在System.Activator.CreateInstance(Type type,Boolean nonPublic)\ r \ n at System.Activator.CreateInstance(Type type)\ r \ n在Hangfire.JobActivator .SimpleJobActivatorScope.Resolve(Type type)\ r \ n at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)\ r \ n在Hangfire.Server.BackgroundJobPerformer。 c__DisplayClass8_0.b__0()\ r \ n在Hangfire.Server .BackgroundJobPerformer.InvokePe 在Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)中的Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context,IEnumerable`1过滤器)\ r \ n的rformFilter(IServerFilter过滤器,PerformingContext preContext,Func 1 continuation)\ r \ n r \ n at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context,IStorageConnection connection,String jobId)“

我没有得到应该为这个结构设置的篝火,因为我没有涉及这里的任何IOC容器。

有人可以帮帮我吗?

演示项目: https : //www.dropbox.com/s/bfjr58y6azgmm3w/HFDemo.zip?dl = 0

答案恰好在例外中

No parameterless constructor defined for this object.

您的OperationStrategy没有无参数构造函数,因此当Hangfire尝试创建此对象时,它不能 – 它通过reflection来实现。 Hangfire无权访问您在计划作业时使用的实例,它会尝试重新创建它。 哪个做不到。

您可以添加无参数构造函数,并使Operations成为公共集合。

这将使您能够像现在一样使用ctor,但也允许对象序列化,由Hangfire存储,然后反序列化并在尝试运行时创建。

 public class OperationStrategy : IOperationStrategy { // paramaterless ctor public OperationStrategy() { Operations = new List(); } public OperationStrategy(params IOperation[] operations) { if (operations == null) throw new ArgumentNullException(nameof(operations)); Operations = operations; } public Output Process(Type type, Input input) { var op = Operations.FirstOrDefault(o => o.AppliesTo(type)); if (op == null) throw new InvalidOperationException($"{operation} not registered."); return op.Process(input); } //property - this can be deserialized by Hangfire public List Operations {get; set;} }