Search code examples
dependency-injectionninjectazure-webjobsazure-webjobs-continuous

How to configure Ninject in call scope binding within Azure Web Job?


I am facing a problem when try to write a web job scheduler. I am using Ninject scope binding using EF Repository pattern. But Only InSingletonScope() work as expected. How to configure it in RequestScope Or Call Scope ?

//Register Context

    Kernel.Bind<MyDbContext>().ToSelf().InSingletonScope();
    Kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>().InSingletonScope();

Solution

  • Problem Solved From One of My Previous Post

    I am posting Step By Step Solution

    (1.) NinjectJobActivator

        public class NinjectJobActivator : IJobActivator
        {
            #region Variable Declaration
            private readonly IResolutionRoot _resolutionRoot;
            #endregion
    
            #region CONSTRUCTOR
            /// <summary>
            /// 
            /// </summary>
            /// <param name="kernel"></param>
           // public NinjectJobActivator(IKernel kernel)
            public NinjectJobActivator(IResolutionRoot resolutionRoot)
            {
                _resolutionRoot = resolutionRoot;
            }
            #endregion
    
    
            #region CreateInstance
            /// <summary>
            /// 
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <returns></returns>
            public T CreateInstance<T>()
            {
                return _resolutionRoot.Get<T>(new CallScopedParameter());
            }
            #endregion
        }
    

    (2) NinjectBindings

    using Ninject.Extensions.Conventions;
    using Ninject.Extensions.NamedScope;
    
    public class NinjectBindings : NinjectModule
        {
            public override void Load()
            {
                //Register Context
                Kernel.Bind<MyDbContext>().ToSelf()
                      .When(x => x.Parameters.OfType<CallScopedParameter>().Any())
                      .InCallScope();  // For Scheduler
    
                Kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>();
    
                //Register Repository
                Kernel.Bind(x => x
               .FromAssemblyContaining<MyDbContext>()
               .SelectAllClasses()
               .InheritedFrom(typeof(IRepository<>))
               .BindDefaultInterface());
    
            }
        }
    

    (3) Program.cs

    static void Main()
            {
                using (IKernel kernel = new StandardKernel(new NinjectBindings()))
                {
                    var config = new JobHostConfiguration()
                    {
                        JobActivator = new NinjectJobActivator(kernel)
                    };
    
                    if (config.IsDevelopment)
                    {
                        config.UseDevelopmentSettings();
                    }
    
                    // Timer Trigger
                    config.UseTimers();
    
                    var host = new JobHost(config);
                    //// The following code ensures that the WebJob will be running continuously
                    host.RunAndBlock();
                }
    
            }
    

    (4) CallScopedParameter

    public sealed class CallScopedParameter : IParameter
        {
            /// <summary>
            /// 
            /// </summary>
            /// <param name="other"></param>
            /// <returns></returns>
            public bool Equals(IParameter other)
            {
                if (other == null)
                {
                    return false;
                }
    
                return other is CallScopedParameter;
            }
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="context"></param>
            /// <param name="target"></param>
            /// <returns></returns>
            public object GetValue(IContext context, ITarget target)
            {
                throw new NotSupportedException("this parameter does not provide a value");
            }
    
            /// <summary>
            /// 
            /// </summary>
            public string Name
            {
                get { return typeof(CallScopedParameter).Name; }
            }
    
            /// <summary>
            /// this is very important
            /// </summary>
            public bool ShouldInherit
            {
                get { return true; }
            }
        }
    

    (5) Azure Web Job Function

    public void DoSomething([TimerTrigger("*/30 *  * * * *")] TimerInfo timer, TextWriter log)
            {
                try
                {
    
                    var tempdetails = _sampleRepository.SearchFor(x=> DateTime.UtcNow > x.DateTo);
    
                    foreach (var detail in tempdetails)
                    {
                        if (detail.ID == 2)
                        {
                            detail.ID = 5;
                        }
                        _sampleRepository.Update(detail);
                    }
    
                     _unitOfWork.Commit();
    
                }
                catch (Exception ex)
                {
                    log.WriteLine(ex.Message);
                }
    
            }