背景
最近在做一个需要,就是在 Job 中捕获异样,而后通过邮件或者音讯的形式推送给指定人员, 在需要实现的过程中遇到的一个注入问题,觉得很有意思, 特此记录。
如果您看了感觉或者曾经有更好的方法,烦请通知我一下,咱们能够独特探讨,如果有中央不对, 也请不吝斧正。
遇到的问题
因为不同性能的 Job 很多, 每一个 Job 中都要实现对产生异样的音讯发送, 现有的 Job 是这样的
为了实现这个需要, 也为了当前更好的保护,我筹备用事件委托的模式去实现, 将对异样音讯发送的业务逻辑拆出,保障职责繁多, 思路如下:
1. 在 Job 和 IJob 两头再加一层 IExceptionJobHandler 接口作为束缚
2. 接口中定义一个发送异样音讯的事件 PushException
3. 而后每一个 Job 在异样时去触发这个事件,内部只须要对立订阅一个事件即可。
到目前这一步是可行的, 尽管不是很完满的设计,然而还是比拟清晰的,然而另外一个问题来了, 我如何通过 Autofac 注入这个 Job 呢,原来间接继承自 Ijob 当初加了一层。
问题剖析
这个问题花了我整整大概 4 个小时的工夫去钻研依赖注入的形式还在网上搜了良久,没什么停顿,而后从新梳理了一下框架依赖注入的代码, 发现是走错路了, 注入 Job 应用的是 Autofac.Extras.Quartz 来实现的, 这下晓得方向了。
var builder = new ContainerBuilder();
builder.RegisterModule(new QuartzAutofacFactoryModule
{ConfigurationProvider = c => schedulerConfig});
这个 QuartzAutofacFactoryModule 外面肯定有我想晓得的货色, 就在 Github 上下载了 Autofac.Extras.Quartz 的源码, 关上一看,果然发现了它的真面目
这外面就是对 Job 依赖注入的, 然而没有发现对 Job 的注册和构建,留神箭头标记的, 它有一个 AutofacJobFactory 类, 接管一个 ILifetimeScope, 而它的作用就是用来构建 Job 为作用域周期失效的服务实例。
解决的方法
- 1. 下面以及剖析出构建 Job 服务实例的, 是一个叫 AutofacJobFactory 的工厂,返回一个 IJob, 那如何把 IExceptionJobHandler 注入进去,让咱们 Job 实例领有这个事件呢?
- 2. 因为咱们的 IExceptionJobHandler 曾经继承了 IJob,也就是说这里间接能够把 Ijob 换成 IExceptionJobHandler, 那该如何实现呢?
继承
- 3. 咱们察看到在 AutofacJobFactory 构建服务的办法是一个
虚办法
, 所以利用继承咱们新建一个 ExtendAutofacJobFactory 来重写它将 Ijob 换成 IExceptionJobHandler
public class ExtendAutofacJobFactory : AutofacJobFactory
{protected override IJob ResolveJobInstance(ILifetimeScope nestedScope, IJobDetail jobDetail)
{
// 验证 Job 是否派生自 IExceptionJobHandler
if (typeof(IExceptionJobHandler).IsAssignableFrom(jobDetail.JobType))
{
IExceptionJobHandler instance = null;
instance = (IExceptionJobHandler)CreateIJob(nestedScope, jobDetail);
// 注册事件对立解决入口
instance.PushException += pushExceptionMessageManager.Value.ExceptionJobHandler
return instance;
}
else
{return base.ResolveJobInstance(nestedScope, jobDetail);
}
}
}
- 4. 咱们须要把重写的结构工厂放入 QuartzAutofacFactoryModule,仍然抉择继承的形式去重写 QuartzAutofacFactoryModule,而后在加载服务时将服务结构工厂换成咱们本人的 ExtendAutofacJobFactory
- 5. 在 Autofac 注册服务中央将 QuartzAutofacFactoryModule 改为 ExtendQuartzAutofacFactoryModule,至此实现了自定义注入。
builder.RegisterModule(new ExtendQuartzAutofacFactoryModule
{ConfigurationProvider = c => schedulerConfig});