Как я могу это сделать? Мне нужно вызвать класс обслуживания, но мне нужно передать параметры - PullRequest
1 голос
/ 16 мая 2011

Мне нужно вызвать что-то в моем приложении, чтобы запустить мой планировщик quartz.net.

Проблема в том, что мне нужно передать репозиторий на мой сервисный уровень, что обычно выполняется с помощью инъекции и привязки.

//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 связывает его, а в IReminderRepo у меня есть

private readonly ISession session;

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

Это также автоматически связывается через nhibernate.

Хотя это не сработает, поскольку global.aspx допускает только конструкторы аргументов.

Так как же добавить нужные классы в эти интерфейсы? Особенно сеанс nhibernate , это самая важная вещь, которая мне нужна.

Редактировать

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>();

// в сервисном модуле

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

Ответы [ 3 ]

0 голосов
/ 16 мая 2011

Вы должны получить экземпляр IScheduledRemindersService из своего контейнера IoC.Контейнер должен взять на себя ответственность за внедрение всех зависимостей для вас, поскольку он создает / разрешает экземпляр.

Я не знаком с NInject, поэтому не могу сказать вам, как это должно быть сделано, но вы должнысделать что-то вроде:

protected void Application_Start()
{
    // 1- register IoC container     
    // 2- resolve instance of IScheduledRemindersService     
    // 3- invoke RemindersService() method on instance    
}
0 голосов
/ 16 мая 2011

Мы используем такой метод в нашем файле Global.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 s, которые требуются Quartz. Поэтому эти классы заданий могут использовать инжекцию на основе конструктора, и Ninject косвенно их создает.

0 голосов
/ 16 мая 2011

Не думаю, что вы хорошо поняли IoC.Когда вы говорите, что ISession автоматически связывается через NHibernate - как вы думаете, что произойдет?NHibernate не справится с этим за вас.Управление сессионным образом жизни - это ваш домен.

Я не думаю, что достаточно кода, чтобы действительно помочь вам.IoC должен будет управлять как сервисом, так и хранилищем, чтобы иметь возможность внедрять одно в другое - если у вас нет прямой ссылки на IoC - что не рекомендуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...