2011-09-12 6 views
6

DIコンテナUnityによって注入された同じIJobインスタンスを常に使用するために、Quartzジョブを登録することはできますか?Quartz、Unity&.NET

class MyJob : IJob { 
... 
[Dependency] IMonitor monitor {get; set;} 
... 
void Execute() 
... 
} 

:私のIJob実装はそれに注入されているモニターのインスタンスを持つことを期待

container.RegisterType<IMonitor, Monitor>(new ContainerControlledLifetimeManager()) 

と:私はユニティDIから来たクラスMonitorの単一のインスタンス「モニター」を持って、私はとして登録WICH石英イベントが発生すると、依存関係が注入される前にIJob.Execute()実装が呼び出されます。これをどうすればいいのですか?代わりに他のDIコンテナやスケジューラを考慮する必要がありますか?

おかげ

答えて

5

クォーツは、すべての火災のイベントにジョブインタフェースの実装を再インスタンス化されます。それはあなたがジョブ実行の間の状態を保存したい場合はIStatefulJobを使用するrecommendedです:

IStatefulJobインスタンスは、通常の IJobインスタンスからわずかに異なるルールに従ってください。主な違いは、ジョブが実行されるたびに、に関連付けられたJobDataMap が再永続化され、次の実行のために の状態が保持されることです。もう1つの違いは、ステートフルな ジョブは同時に実行できないということです。つまり、IJob.Executeメソッドの完了前に発生する新しいトリガー は、 が遅延します。クォーツtutorialから

StatefulJob

さて、ジョブの状態データ(別名JobDataMap)に関するいくつかの追加の注意事項:ジョブ・インスタンスは、 "ステートフル" または「非として定義することができ - 状態 "。 ステートフルでないジョブは、 がスケジューラに追加された時点で保存されているJobDataMapのみを持ちます。これは、ジョブの実行中にジョブデータマップの の内容に行われた変更が失われ、 となり、次回の実行時にジョブでは見られないことを意味します。 はおそらく推測されていますが、ステートフルなジョブはちょうど反対です。ジョブの実行ごとにJobDataMap が再格納されます。 の1つの副作用は、ジョブをステートフルにするということは、同時に実行できないということです。または、 つまり、ジョブがステートフルで、ジョブがすでに実行中のときにトリガーが ジョブを「起動」しようとすると、前の実行が完了するまで、トリガーによってブロックされます(待機) 。

Jobインターフェイスではなく、StatefulJob インターフェイスを実装することによって、ジョブをステートフルとしてマークします。

あなたのための別のオプションは、あなた自身のJobFactoryを実装することです: 次のことができますか今では明らかでない場合があり、このトピックに関する

仕事「インスタンス」

ワン最後のポイント1つのジョブクラスを作成し、多数のインスタンス「 定義」をスケジューラ内に保存します。 のJobDetails - それぞれ独自のプロパティセットとJobDataMap - を持っており、それらをすべてスケジューラに追加します。

トリガが起動すると、関連付けられているジョブは、 スケジューラで設定されたJobFactoryによってインスタンス化されます。デフォルトのJobFactory は、単にジョブクラスのnewInstance()を呼び出します。 独自のJobFactoryの実装を作成して、アプリケーションのIoCまたはDIコンテナに ジョブインスタンスを生成/初期化する などを実現することができます。

+0

まあ、私は同じIJobインスタンス上に保持するに興味がないんだけど、私が欲しいのは同じiMonitorのは、それぞれの新しいIJobインスタンスに注入していることです... – j040p3d20

+2

ストアJobDataMapであなたの「モニター」への参照独自のJobFactoryを実装することもできます。 – Dmitry

+0

'StatefulJob'インターフェースは非推奨です... http://quartz-scheduler.org/documentation/quartz-2.x/new-in-quartz-2注釈を使うことをお勧めします – Jaider

2

独自のJobFactoryを実装することで、これを行うことができます。 、そして、

public interface IJobFactory 
{ 
    /// <summary> 
    /// Called by the scheduler at the time of the trigger firing, in order to 
    /// produce a <see cref="IJob" /> instance on which to call Execute. 
    /// </summary> 
    /// <remarks> 
    /// <p> 
    /// It should be extremely rare for this method to throw an exception - 
    /// basically only the 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 
    /// <see cref="TriggerState.Error" /> state, which will require human 
    /// intervention (e.g. an application restart after fixing whatever 
    /// configuration problem led to the issue wih instantiating the Job. 
    /// </p> 
    /// 
/// </remarks> 
    /// <param name="bundle"> 
    /// The TriggerFiredBundle from which the <see cref="JobDetail" /> 
    /// and other info relating to the trigger firing can be obtained. 
    /// </param> 
    /// <throws> SchedulerException if there is a problem instantiating the Job. </throws> 
    /// <returns> the newly instantiated Job 
    /// </returns> 
    IJob NewJob(TriggerFiredBundle bundle); 
} 

あなたの仕事の工場のタイプにスケジューラのquartz.scheduler.jobFactory.typeプロパティを設定します。あなたはIJobFactoryインタフェースを実装する必要があります。参考のため

は、ここquartz.netが使用するデフォルトのジョブの工場があります:

public class SimpleJobFactory : IJobFactory 
{ 
    private static readonly ILog Log = LogManager.GetLogger(typeof (SimpleJobFactory)); 

    /// <summary> 
    /// Called by the scheduler at the time of the trigger firing, in order to 
    /// produce a <see cref="IJob" /> instance on which to call Execute. 
    /// </summary> 
    /// <remarks> 
    /// It should be extremely rare for this method to throw an exception - 
    /// basically only the 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 
    /// <see cref="TriggerState.Error" /> state, which will require human 
    /// intervention (e.g. an application restart after fixing whatever 
    /// configuration problem led to the issue wih instantiating the Job. 
/// </remarks> 
    /// <param name="bundle">The TriggerFiredBundle from which the <see cref="JobDetail" /> 
    /// and other info relating to the trigger firing can be obtained.</param> 
    /// <returns>the newly instantiated Job</returns> 
    /// <throws> SchedulerException if there is a problem instantiating the Job. </throws> 
    public virtual IJob NewJob(TriggerFiredBundle bundle) 
    { 
     JobDetail jobDetail = bundle.JobDetail; 
     Type jobType = jobDetail.JobType; 
     try 
     { 
      if (Log.IsDebugEnabled) 
      { 
       Log.Debug(string.Format(CultureInfo.InvariantCulture, "Producing instance of Job '{0}', class={1}", jobDetail.FullName, jobType.FullName)); 
      } 

      return (IJob) ObjectUtils.InstantiateType(jobType); 
     } 
     catch (Exception e) 
     { 
      SchedulerException se = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Problem instantiating class '{0}'", jobDetail.JobType.FullName), e); 
      throw se; 
     } 
    } 
} 

興味深い行は次のようになります。

return (IJob) ObjectUtils.InstantiateType(jobType); 
5

Quartz.Unityを見てください。

https://www.nuget.org/packages/Quartz.Unity/1.0.1

ドクは非常に希薄であるが、あなたがする必要があるすべてはnugetパッケージとあなたのコンテナ設定に次の行を追加していることが表示されます。

var container = new UnityContainer().AddNewExtension<Quartz.Unity.QuartzUnityExtension>(); 
0

SimpleJobFactoryをオーバーライドし、springを使用してジョブクラスをインスタンス化するCustomJobfactoryを作成します。

/// <summary> 
/// Custom Job Factory 
/// </summary> 
public class CustomJobFactory : SimpleJobFactory 
{ 
    /// <summary> 
    /// Application context 
    /// </summary> 
    private IApplicationContext context; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="CustomJobFactory" /> class. 
    /// </summary> 
    public CustomJobFactory() 
    { 
     this.context = ContextRegistry.GetContext(); 
    } 

    /// <summary> 
    /// Creates a new job instance 
    /// </summary> 
    /// <param name="bundle">Trigger bundle</param> 
    /// <param name="scheduler">Job scheduler</param> 
    /// <returns></returns> 
    public override IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) 
    { 
     IJobDetail jobDetail = bundle.JobDetail; 
     Type jobType = jobDetail.JobType; 
     return this.context.GetObject(jobType.Name) as IJob; 
    } 

    /// <summary> 
    /// Return job 
    /// </summary> 
    /// <param name="job">Job instance</param> 
    public override void ReturnJob(IJob job) 
    { 
    } 
}