Dependency injection 静态函数作用域中WebJobs for DbContext的依赖项注入Ninject

Dependency injection 静态函数作用域中WebJobs for DbContext的依赖项注入Ninject,dependency-injection,azure-webjobs,azure-webjobssdk,Dependency Injection,Azure Webjobs,Azure Webjobssdk,有没有一种方法可以钩住WebJobs函数的执行,这样我们就可以在每个函数上有一个作用域?大概是这样的: kernel.Bind().ToSelf().InWebJobFunctionScope() 我想使用Ninject中的InScope(),但我不知道在哪里可以找到类似于静态HttpContext.Current的东西,但用于当前正在运行的WebJob。我知道这是一个旧版本,但我有相同的剧本。由于是最新版本的web作业,您可以使用实例和实例方法,并传入自定义IJobActivator实例。这非

有没有一种方法可以钩住WebJobs函数的执行,这样我们就可以在每个函数上有一个作用域?大概是这样的:

kernel.Bind().ToSelf().InWebJobFunctionScope()


我想使用Ninject中的
InScope()
,但我不知道在哪里可以找到类似于静态
HttpContext.Current的东西,但用于当前正在运行的WebJob。

我知道这是一个旧版本,但我有相同的剧本。由于是最新版本的web作业,您可以使用实例和实例方法,并传入自定义IJobActivator实例。这非常容易

它与Ninject完美配合。我还没有看到任何令人讨厌的例子,所以

public class MyJobActivator : IJobActivator
{
    protected readonly IKernel _kernel;

    public MyJobActivator(IKernel kernel)
    {
        _kernel = kernel;
    }

    public T CreateInstance<T>()
    {
        return _kernel.Get<T>();
    }
}


public class MyBindings : NinjectModule
{
    public override void Load()
    {     
        Bind(typeof(DbContext)).To(typeof(MyEntities));
    }
}

class Program
{        
    static void Main()
    {
        using (IKernel kernel = new StandardKernel(new MyBindings()))
        {
            var jobHostConfiguration = new JobHostConfiguration
            {
                JobActivator = new MyJobActivator(kernel)
            };

            var host = new JobHost(jobHostConfiguration);

            // The following code will invoke a function called ManualTrigger and 
            // pass in data (value in this case) to the function
            host.Call(typeof(Reminders).GetMethod("ManualTrigger"), new { value = 20 });
        }
    }
}


public class Reminders
{
    private readonly IMyService _myService;

    public Reminders(IMyService myService)
    {
        _myService = myService;
    }

    // This function will be triggered based on the schedule you have set for this WebJob
    // This function will enqueue a message on an Azure Queue called queue
    [NoAutomaticTrigger]
    public async Task ManualTrigger(TextWriter log, int value, TextWriter logger)
    {
        try
        {   
            // process the notification request
            await _myService.FindAndSendReminders();
            await _myService.SaveChangesAsync();
        }
        catch (Exception e)
        {
            logger.WriteLine(e.Message);
            Console.WriteLine(e.Message);
            throw;
        }
    }
}
我根据为Autofac找到的一篇文章改编了我的原始代码

另见

以及连续的网络作业


Hi-JS,我已经打开了一个问题,但是你能使用InThreadScope吗?@Thomas我原以为线程作用域在使用异步/等待模式时会开始出现错误行为。我尝试对每个静态函数使用BeginBlock,但一切都失败了。因此,我现在使用InNamedScope和CreateNameScope以及PreserveContextNuGet包,以最终获得适合我的db上下文的东西。。。确实很痛苦,我怀疑name scope应该是这样工作的。出于某些原因,我有理由相信这不适用于并发,和/或在使用GetMethod()技巧调用时不起作用@Thomas,你认为这涵盖了我们很久以前一直在寻找的东西吗:P?jsgoupil我已经更新了不需要使用getmethod的连续Web作业的答案。希望这会有所帮助。@Troyka您对触发的webjobs中实体框架DbContext对象的生命周期有什么看法?显然,webjob进程一直处于活动状态,这意味着我可能应该将DbContext的作用域设置为一个单例,但另一方面,每个消息都涉及函数,因此我可以对每个函数执行的DbContext进行作用域设置。你推荐什么?
public class Program
{        
    static void Main()
    {
        using (IKernel kernel = new StandardKernel(new MyBindings()))
        {
            var jobHostConfiguration = new JobHostConfiguration
            {
                JobActivator = new MyJobActivator(kernel)
            };

            var host = new JobHost(jobHostConfiguration);

            // The following code ensures that the WebJob will be running continuously
            host.RunAndBlock();
        }
    }
}


public class Functions
{
    private readonly IMyService _myService;

    public Functions(IMyService myService)
    {
        _myService = myService;
    }        

    public async Task ProcessReminders([QueueTrigger("reminder-requests")] string notificationMessage, TextWriter logger)
    {
        try
        {   
            // process the notification request
            await _myService.FindAndSendReminders();
            await _myService.SaveChangesAsync();
        }
        catch (Exception e)
        {
            logger.WriteLine(e.Message);
            Console.WriteLine(e.Message);
            throw;
        }
    }
}