1

我需要在我的應用程序啓動時調用某些東西來啓動我的quartz.net調度程序。我該怎麼做?我需要調用一個服務類,但我需要傳遞參數

問題是我需要將存儲庫傳遞到我的服務層,通常是使用ninject和依賴注入完成的。

//global.aspx 

public class MvcApplication : System.Web.HttpApplication 
    { 
     private readonly IScheduledRemindersService scheduledRemindersService; 

     public MvcApplication(IScheduledRemindersService 
      scheduledRemindersService) 
     { 
      this.scheduledRemindersService = scheduledRemindersService; 
     } 

     protected void Application_Start() 
     { 
      //other default stuff here like mvc routers. 
      scheduledRemindersService.RemindersSchedule(); 

     } 
} 

    private readonly IReminderRepo reminderRepo; 
    public ScheduledRemindersService(IReminderRepo reminderRepo) 
    { 
     this.reminderRepo = reminderRepo; 
    } 


private readonly IReminderRepo reminderRepo; 


    public ScheduledRemindersService(IReminderRepo reminderRepo) 
    { 
     this.reminderRepo = reminderRepo; 
    } 

我已經NHibernate的設置,所以當它似乎IReminderRepo它shoudl結合它在IReminderRepo我有

private readonly ISession session; 

public ReminderRepo(ISession session) 
{ 
    this.session = session; 
} 

這也將通過NHibernate的都會自動綁定。

雖然global.aspx只允許沒有參數構造函數,但這不起作用。

那麼如何向這些接口注入正確的類? 尤其是nhibernate session這是我需要的最重要的東西。

編輯

public class NhibernateSessionFactoryProvider : Provider<ISessionFactory> 
    { 
     protected override ISessionFactory CreateInstance(IContext context) 
     { 
      var sessionFactory = new NhibernateSessionFactory(); 
      return sessionFactory.GetSessionFactory(); 
     } 
    } 

    public class NhibernateModule : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<ISessionFactory>().ToProvider<NhibernateSessionFactoryProvider>().InSingletonScope(); 
      Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope(); 
     } 
    } 

//在global.aspx

protected IKernel CreateKernel() 
    { 
     var modules = new INinjectModule[] 
          { 
          new NhibernateModule(), 
          new ServiceModule(), 
          new RepoModule(), 
          }; 

     return new StandardKernel(modules); 
    } 

//在RepoModule()

Bind<IReminderRepo>().To<ReminderRepo>(); 

//在serviceModule

Bind<IScheduledRemindersService>().To<ScheduledRemindersService>() 

回答

0

我們採用的方法是這樣在我們的全球的.asax。出於這樣的目的CS文件(它會從的Application_Start稱爲:

private static void SetupScheduling(IKernel kernel) 
    { 
     var scheduler = SchedulerUtil.Scheduler; 
     scheduler.JobFactory = kernel.Get<IJobFactory>(); 
     scheduler.Start(); 
    } 

而且我們有IJobFactory綁定到下面的類:

public class QuartzJobFactory : IJobFactory 
{ 
    private readonly IObjectFactory<IJob> _jobFactory; 
    private readonly LogService _logService; 

    public QuartzJobFactory(IObjectFactory<IJob> jobFactory, 
     LogService logService) 
    { 
     _jobFactory = jobFactory; 
     _logService = logService; 
    } 

    /// <summary> 
    /// Called by the scheduler at the time of the trigger firing, in order to 
    ///    produce a <see cref="T:Quartz.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="F:Quartz.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="T:Quartz.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> 
    public IJob NewJob(TriggerFiredBundle bundle) 
    { 
     Type jobType; 
     try 
     { 
      Require.ThatArgument(bundle != null); 
      Require.ThatArgument(bundle.JobDetail != null); 
      jobType = bundle.JobDetail.JobType; 
     } 
     catch (Exception e) 
     { 
      // This shouldn't ever happen, but if it does I want to know about it. 
      _logService.LogCritical(() => e.ToString()); 
      throw; 
     } 
     try 
     { 
      return _jobFactory.GetObject(jobType); 
     } 
     catch (Exception e) 
     { 
      _logService.LogCritical(() => "An exception was thrown while creating job of type {0}: {1}" 
       .With(jobType, e)); 
      throw; 
     } 
    } 
} 

而且IObjectFactory是一個簡單的界面,只是抽象了的內核,從而我們不依賴於Ninject無處不在:

/// <summary> 
/// Similar to IFactory, but this factory produces types based on a dynamic 
/// <see cref="Type"/> object. If the given Type object is not of the given 
/// "T" type, an exception will be thrown. 
/// </summary> 
/// <typeparam name="T">A parent-level type representing what sort of values 
/// are expected. If the type could be anything, try using <see cref="object"/> 
/// </typeparam> 
public interface IObjectFactory<out T> 
{ 
    T GetObject(Type type); 
} 

IObjectFactory然後綁定到一個像這樣的類:

/// <summary> 
/// This implementation of the generic <see cref="IFactory{T}"/> and 
/// <see cref="IObjectFactory{T}"/> classes uses Ninject to supply instances of 
/// the given type. It should not be used explicitly, but will rather be used 
/// by the DI framework itself, to provide instances to services that depend on 
/// IFactory objects. 
/// This implementation takes the injection context as a constructor argument, so that 
/// it can reuse elements of the context when it is asked to supply an instance 
/// of a type. 
/// In order for this to work, you will need to define bindings from <see cref="IFactory{T}"/> 
/// and <see cref="IObjectFactory{T}"/> to this class, as well as a binding from 
/// <see cref="IContext"/> to a method or factory that returns the current binding 
/// context. 
/// </summary> 
/// <typeparam name="T">The Type of the service to be produced by the Get method.</typeparam> 
public class InjectionFactory<T> : IFactory<T>, IObjectFactory<T> 
{ 
    private readonly IKernel _kernel; 
    private readonly IParameter[] _contextParameters; 

    /// <summary> 
    /// Constructs an InjectionFactory 
    /// </summary> 
    /// <param name="injectionContext">The context in which this injection is taking place.</param> 
    public InjectionFactory(IContext injectionContext) 
    { 
     _contextParameters = injectionContext.Parameters 
      .Where(p => p.ShouldInherit).ToArray(); 
     _kernel = injectionContext.Kernel; 
    } 

    public T Get() 
    { 
     try 
     { 
      return _kernel.Get<T>(_contextParameters.ToArray()); 
     } 
     catch (Exception e) 
     { 
      throw e.Wrap(() => "An error occurred while attempting to instantiate an object of type <{0}>".With(typeof(T))); 
     } 
    } 

    public T GetObject(Type type) 
    { 
     if (type == null) 
     { 
      throw new ArgumentNullException("type"); 
     } 
     if (!typeof (T).IsAssignableFrom(type)) 
     { 
      throw new InvalidCastException(type.FullName + " is not a child type of " + typeof (T).FullName); 
     } 
     try 
     { 
      return (T)_kernel.Get(type, _contextParameters); 
     } 
     catch (Exception e) 
     { 
      throw e.Wrap(() => "An error occurred while attempting to instantiate an object of type <{0}>".With(typeof(T))); 
     } 
    } 
} 

...用結合,看起來像這樣:

Bind(typeof (IObjectFactory<>)).To(typeof (InjectionFactory<>)); 
    // Injection factories ask for the injection context. 
    Bind(typeof (IContext)).ToMethod(c => c.Request.ParentContext); 

所以整體效果,我們使用Ninject內核創建IJobFactory,它採用構造器注入到採取IObjectFactory<IJob>,它被調用來產生石英需要的任何IJob。這些作業類因此可以使用基於構造函數的注入,而Ninject間接實例化它們。

0

我不認爲你已經很好地理解了IoC。當你說ISession會通過NHibernate自動綁定 - 你在想什麼? NHibernate不會爲你管理。會議生活方式管理是你的領域。

我不認爲有足夠的代碼來真正幫助你。服務和存儲庫需要由您的IoC管理,以便能夠將其中一個注入另一個 - 除非您有直接引用的IoC - 這是不推薦的。

+0

我有一個會話工廠,它提供了通過ninjects生命週期進行管理的會話。會話工廠貫穿於我的應用程序的生命週期,每個Web請求都會獲得它自己的會話,並在Web請求結束時結束。 – chobo2 2011-05-15 20:46:54

+0

@civista - 我更新了我的帖子。基本上我只是打電話給我的服務層 - >這需要我的回購 - >有一個會議。這一切都有效,我沒有任何直接參考IoC。 – chobo2 2011-05-15 20:53:51

+0

我使用城堡WCF工具來獲取我的WCF服務和城堡石英集成上的IoC,以便在我的石英作業上獲得IoC – iwayneo 2011-05-16 06:19:23

0

您應該從IoC容器中獲取IScheduledRemindersService的實例。在創建/解析實例時,容器應負責爲您注入所有依賴項。

我不熟悉NInject所以我不能告訴你應該怎麼做,但你應該做的線沿線的東西:

protected void Application_Start() 
{ 
    // 1- register IoC container  
    // 2- resolve instance of IScheduledRemindersService  
    // 3- invoke RemindersService() method on instance  
} 
+0

@ -cs。是的,我通過IoC容器註冊,我將IScheduledRemindersService綁定到ScheduledRemindersService,不確定3是什麼,但我正在使用構造函數注入。 – chobo2 2011-05-15 20:51:18

+0

也許我並不完全清楚你想要做什麼。從我看,我不認爲你需要這裏的構造函數。爲什麼不直接從Application_Start中的IoC中檢索IScheduledReminderService實例並在該上下文中使用它?你需要在其他地方使用它嗎? – csano 2011-05-15 21:03:41

+0

@ScheduledRemindersService - 我不在其他地方使用服務,但我不確定如何使用上下文。 – chobo2 2011-05-15 22:56:50

相關問題