Class PropertySettingJobFactory
A JobFactory that instantiates the Job instance (using its public parameterless constructor), and then attempts to set all values from the IJobExecutionContext's merged JobDataMap onto properties of the job.
public class PropertySettingJobFactory : SimpleJobFactory, IJobFactory
- Inheritance
-
PropertySettingJobFactory
- Implements
- Derived
- Inherited Members
Remarks
By default an entry in the JobDataMap that does not map to a property on your job class is ignored, because a map is allowed to carry values the job reads for itself. Set PropertyMismatchBehavior to Warn to log those — useful for troubleshooting a misspelled property name, noisy if you regularly (and purposely) have extra things in your map — or to Throw to fail the instantiation outright.
Constructors
PropertySettingJobFactory(ILoggerFactory?)
public PropertySettingJobFactory(ILoggerFactory? loggerFactory = null)
Parameters
loggerFactoryILoggerFactoryWhere this factory and its derived types create their loggers. A factory the container builds is handed the application's; one constructed by hand —
UseJobFactory(instance)— is handed nothing and reads LogProvider, as before. A factory rather than a logger, because PropertySettingJobFactory logs under its own category and has to be able to pass the same source down.
Properties
PropertyMismatchBehavior
What happens when a key (name) and value (type) found in the JobDataMap does not correspond to a property setter on the job class. Defaults to Ignore.
public virtual PropertyMismatchBehavior PropertyMismatchBehavior { get; set; }
Property Value
Methods
BuildJobDataMap(TriggerFiredBundle, IScheduler)
Builds the map whose entries are applied to the job's properties: the trigger's data merged over the job's.
protected virtual JobDataMap BuildJobDataMap(TriggerFiredBundle bundle, IScheduler scheduler)
Parameters
bundleTriggerFiredBundleschedulerIScheduler
Returns
Remarks
Until 4.0 the scheduler context was merged in as well, underneath both. That injected every
context entry into every fire — including the service-provider entry the DI integration seeds,
which no job has a property for, so with Throw every
container-hosted fire failed. A job that wants a context value reads
context.Scheduler.Context in Execute(IJobExecutionContext, CancellationToken); a factory that wants the old
behavior overrides this method, which is handed the scheduler for exactly that reason.
ConvertValueIfNecessary(Type, object?)
Coerces a JobDataMap value into the type the job's property takes.
protected virtual object? ConvertValueIfNecessary(Type requiredType, object? newValue)
Parameters
Returns
Remarks
The seam a derived factory overrides to convert a value some other way. It is deliberately the only thing between the map and the property, so an override sees every value the factory binds.
CreateJob(TriggerFiredBundle, IScheduler, CancellationToken)
Called by the scheduler at the time of the trigger firing, in order to produce a IJob instance on which to call Execute.
public override ValueTask<JobScope> CreateJob(TriggerFiredBundle bundle, IScheduler scheduler, CancellationToken cancellationToken = default)
Parameters
bundleTriggerFiredBundleThe TriggerFiredBundle from which the IJobDetail and other info relating to the trigger firing can be obtained.
schedulerISchedulerThe scheduler the job will run under, made available to the job through its execution context.
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
Remarks
It should be extremely rare for this method to throw an exception - basically only the case where there is no way at all to instantiate and prepare the Job for execution. When the exception is thrown, the Scheduler will move all triggers associated with the Job into the Error state, which will require human intervention (e.g. an application restart after fixing whatever configuration problem led to the issue with instantiating the Job).
Exceptions
- SchedulerException
The job could not be instantiated, or a value in the merged job data map does not match a settable property of the job and PropertyMismatchBehavior says to throw.
CreateJobInstance(TriggerFiredBundle, IScheduler, CancellationToken)
Produces the job instance, before any JobDataMap properties are applied to it.
protected virtual ValueTask<JobScope> CreateJobInstance(TriggerFiredBundle bundle, IScheduler scheduler, CancellationToken cancellationToken = default)
Parameters
bundleTriggerFiredBundleThe TriggerFiredBundle from which the IJobDetail and other info relating to the trigger firing can be obtained.
schedulerISchedulera handle to the scheduler that is about to execute the job
cancellationTokenCancellationTokenThe cancellation instruction.
Returns
Remarks
This is the extension point for derived factories that need to change how the job is built — resolving it from a container, for example — without overriding CreateJob(TriggerFiredBundle, IScheduler, CancellationToken) and reimplementing the property setting this class exists to provide.
It returns a ValueTask<TResult> so an override can await, but prefer to
keep the synchronous path synchronous: an async override puts the work inside a state
machine, which restores the caller's ExecutionContext when its
synchronous part returns and so discards any AsyncLocal<T> the
override set. Ambient context established here has to survive into Execute(IJobExecutionContext, CancellationToken)
(#1528). Return a completed ValueTask<TResult> when nothing needs awaiting.
SetObjectProperties(object, JobDataMap)
Sets the object properties.
public virtual void SetObjectProperties(object obj, JobDataMap data)
Parameters
objobjectThe object to set properties to.
dataJobDataMapThe data to set.
SetObjectProperty(object, string, object?)
Sets specific property to object, handles conversion and error conditions.
[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "The job instance is of the job detail's declared type or of a registered implementation of it, and both are annotated where they enter Quartz. See the remarks.")]
protected virtual void SetObjectProperty(object job, string name, object? value)
Parameters
jobobjectJob instance to set property value to.
namestringProperty name to set.
valueobjectValue to set.
Remarks
The property is found on the instance's own type rather than on the job detail's declared one,
because a factory is allowed to hand back something else — AddJobType<TJob, TImpl>
registers exactly that — and the data belongs to whatever was built. Both of those types are
annotated where they enter Quartz, so their public properties survive trimming; the analyzer
cannot see the link because the instance arrives here as an object. A job factory
written from scratch that returns a type nothing else references is the one case this does not
cover, and such a factory has to root its own jobs.