C# WebJob依赖项注入绑定到泛型类

C# WebJob依赖项注入绑定到泛型类,c#,generics,azure-webjobs,C#,Generics,Azure Webjobs,我有一系列用于处理WebJobs的类,这些类类似于: public class EnvelopeSalutationJob : BatchJob { public EnvelopeSalutationJob( StringWriter swLogger ) : base( swLogger, "Envelope Salutation Job" ) { } [ Singleton() ] public async Task ProcessM

我有一系列用于处理WebJobs的类,这些类类似于:

public class EnvelopeSalutationJob : BatchJob
{
    public EnvelopeSalutationJob( StringWriter swLogger )
        : base( swLogger, "Envelope Salutation Job" )
    {
    }

    [ Singleton() ]
    public async Task ProcessMessage(
        [ QueueTrigger( "%" + nameof( ContainerQueueConstants.EnvelopeSalutation ) + "%" ) ] EnvelopeSalutationMessage msg,
        TextWriter azureLogWriter
    )
    {
        PhaseNames.SetNames( "Processing Homes", "Job Completed" );

        await ExecuteFromMessage( msg, azureLogWriter, Launch );
    }
}
public static class ContainerConfig
{
    public static IContainer GetContainer()
    {
        var builder = new ContainerBuilder();

        // per job
        builder.RegisterType<StringWriter>();

        // jobs
        builder.RegisterType<EnvelopeSalutationJob>();

        return builder.Build();
    }
}
public class EnvelopeSalutationJob<TContext, TUser>
    : BatchJob<TContext, TUser>
    where TContext : IdentityDbContext<TUser>, ICampaignContext, new()
    where TUser : IdentityUser, INamedUser
{
    public EnvelopeSalutationJob( StringWriter swLogger )
        : base( swLogger, "Envelope Salutation Job" )
    {
    }
    [ Singleton() ]
    public async Task ProcessMessage(
        [ QueueTrigger( "%" + nameof( ContainerQueueConstants.EnvelopeSalutation ) + "%" ) ] EnvelopeSalutationMessage msg,
        TextWriter azureLogWriter
    )
    {
        PhaseNames.SetNames( "Processing Homes", "Job Completed" );

        await ExecuteFromMessage( msg, azureLogWriter, Launch );
    }
}
使用AutoFac作为DI框架,这些功能非常有效,配置如下:

public class EnvelopeSalutationJob : BatchJob
{
    public EnvelopeSalutationJob( StringWriter swLogger )
        : base( swLogger, "Envelope Salutation Job" )
    {
    }

    [ Singleton() ]
    public async Task ProcessMessage(
        [ QueueTrigger( "%" + nameof( ContainerQueueConstants.EnvelopeSalutation ) + "%" ) ] EnvelopeSalutationMessage msg,
        TextWriter azureLogWriter
    )
    {
        PhaseNames.SetNames( "Processing Homes", "Job Completed" );

        await ExecuteFromMessage( msg, azureLogWriter, Launch );
    }
}
public static class ContainerConfig
{
    public static IContainer GetContainer()
    {
        var builder = new ContainerBuilder();

        // per job
        builder.RegisterType<StringWriter>();

        // jobs
        builder.RegisterType<EnvelopeSalutationJob>();

        return builder.Build();
    }
}
public class EnvelopeSalutationJob<TContext, TUser>
    : BatchJob<TContext, TUser>
    where TContext : IdentityDbContext<TUser>, ICampaignContext, new()
    where TUser : IdentityUser, INamedUser
{
    public EnvelopeSalutationJob( StringWriter swLogger )
        : base( swLogger, "Envelope Salutation Job" )
    {
    }
    [ Singleton() ]
    public async Task ProcessMessage(
        [ QueueTrigger( "%" + nameof( ContainerQueueConstants.EnvelopeSalutation ) + "%" ) ] EnvelopeSalutationMessage msg,
        TextWriter azureLogWriter
    )
    {
        PhaseNames.SetNames( "Processing Homes", "Job Completed" );

        await ExecuteFromMessage( msg, azureLogWriter, Launch );
    }
}
公共静态类容器配置
{
公共静态IContainer GetContainer()
{
var builder=new ContainerBuilder();
//每项工作
RegisterType();
//工作
RegisterType();
返回builder.Build();
}
}
但最近我想将作业“一般化”,这样它们就不会与特定的DBContext绑定。我尝试使用这样的模式:

public class EnvelopeSalutationJob : BatchJob
{
    public EnvelopeSalutationJob( StringWriter swLogger )
        : base( swLogger, "Envelope Salutation Job" )
    {
    }

    [ Singleton() ]
    public async Task ProcessMessage(
        [ QueueTrigger( "%" + nameof( ContainerQueueConstants.EnvelopeSalutation ) + "%" ) ] EnvelopeSalutationMessage msg,
        TextWriter azureLogWriter
    )
    {
        PhaseNames.SetNames( "Processing Homes", "Job Completed" );

        await ExecuteFromMessage( msg, azureLogWriter, Launch );
    }
}
public static class ContainerConfig
{
    public static IContainer GetContainer()
    {
        var builder = new ContainerBuilder();

        // per job
        builder.RegisterType<StringWriter>();

        // jobs
        builder.RegisterType<EnvelopeSalutationJob>();

        return builder.Build();
    }
}
public class EnvelopeSalutationJob<TContext, TUser>
    : BatchJob<TContext, TUser>
    where TContext : IdentityDbContext<TUser>, ICampaignContext, new()
    where TUser : IdentityUser, INamedUser
{
    public EnvelopeSalutationJob( StringWriter swLogger )
        : base( swLogger, "Envelope Salutation Job" )
    {
    }
    [ Singleton() ]
    public async Task ProcessMessage(
        [ QueueTrigger( "%" + nameof( ContainerQueueConstants.EnvelopeSalutation ) + "%" ) ] EnvelopeSalutationMessage msg,
        TextWriter azureLogWriter
    )
    {
        PhaseNames.SetNames( "Processing Homes", "Job Completed" );

        await ExecuteFromMessage( msg, azureLogWriter, Launch );
    }
}
公共类信封解析作业
:批处理作业
其中TContext:IdentityDbContext,ICampaignContext,new()
where TUser:IdentityUser,INamedUser
{
公共信封解析作业(StringWriter swLogger)
:base(swLogger,“信封称呼作业”)
{
}
[Singleton()]
公共异步任务处理消息(
[QueueTrigger(“%”+nameof(ContainerQueueConstants.EnvelopesAssetation)+“%”]EnvelopesAssetationMessage消息,
文字写手azureLogWriter
)
{
PhaseNames.SetNames(“处理房屋”、“作业完成”);
等待ExecuteFromMessage(msg、azureLogWriter、Launch);
}
}
AutoFac配置更改为:

public static class ContainerConfig
{
    public static IContainer GetContainer()
    {
        var builder = new ContainerBuilder();

        // per job
        builder.RegisterType<StringWriter>();

        // jobs
        builder.RegisterType<EnvelopeSalutationJob<ConnellJobContext, ConnellUser>>();

        return builder.Build();
    }
}
公共静态类容器配置
{
公共静态IContainer GetContainer()
{
var builder=new ContainerBuilder();
//每项工作
RegisterType();
//工作
RegisterType();
返回builder.Build();
}
}
不幸的是,这不起作用。WebJobs控制台应用程序启动正常,但它抱怨:

找不到作业函数。试着把你的工作分类和方法 公众


无法将作业绑定到泛型类的实例吗?

根据您的描述,我已经测试了这个问题,我可以按如下方式重现这个问题:

在我检查了git上的源代码之后,我发现它将使用
IsJobClass
,调用它来过滤类型,如下所示:

public static bool IsJobClass(Type type)
{
    if (type == null)
    {
        return false;
    }

    return type.IsClass
        // For C# static keyword classes, IsAbstract and IsSealed both return true. Include C# static keyword
        // classes but not C# abstract keyword classes.
        && (!type.IsAbstract || type.IsSealed)
        // We only consider public top-level classes as job classes. IsPublic returns false for nested classes,
        // regardless of visibility modifiers. 
        && type.IsPublic
        && !type.ContainsGenericParameters;
}
public bool IsJobMethod(MethodInfo method)
{
    if (method.ContainsGenericParameters)
    {
        return false;
    }

    if (method.GetCustomAttributesData().Any(HasJobAttribute))
    {
        return true;
    }

    if (method.GetParameters().Length == 0)
    {
        return false;
    }

    if (method.GetParameters().Any(p => p.GetCustomAttributesData().Any(HasJobAttribute)))
    {
        return true;
    }

    return false;
}
此外,将使用
IsJobMethod
过滤方法,如下所示:

public static bool IsJobClass(Type type)
{
    if (type == null)
    {
        return false;
    }

    return type.IsClass
        // For C# static keyword classes, IsAbstract and IsSealed both return true. Include C# static keyword
        // classes but not C# abstract keyword classes.
        && (!type.IsAbstract || type.IsSealed)
        // We only consider public top-level classes as job classes. IsPublic returns false for nested classes,
        // regardless of visibility modifiers. 
        && type.IsPublic
        && !type.ContainsGenericParameters;
}
public bool IsJobMethod(MethodInfo method)
{
    if (method.ContainsGenericParameters)
    {
        return false;
    }

    if (method.GetCustomAttributesData().Any(HasJobAttribute))
    {
        return true;
    }

    if (method.GetParameters().Length == 0)
    {
        return false;
    }

    if (method.GetParameters().Any(p => p.GetCustomAttributesData().Any(HasJobAttribute)))
    {
        return true;
    }

    return false;
}
根据我的理解,Azure WebJobs SDK目前不支持将作业绑定到泛型类的实例。您可以定义
BaseDbContext
并利用构造函数依赖项注入来初始化
DbContext
实例。此外,您还可以添加您的反馈