可以看到LunaHangfireRunnerBase類的屬性註入
接上一篇整合了一個命令行程序的框架我增加了一點功能
aop和定時任務
這次更新主要增加了審計日誌還有集成了hangfire做定時任務
-
先來看審計日誌部分,審計日誌主要是使用了Windsor的動態代理功能.每一個添加了Audited特性的方法或者類,在方法被調用時會輸出參數和值.使用時只要在需要審計的service上增加Audited特性即可
[Audited] public class DemoService : LunaServiceBase, IDemoService { public string GetMessage(string name) { Logger.Info($"GetMessage {name}"
同時在start上增加了一個可選參數.目前只有一個設置項,就是是否開啟審計日誌功能.如果不開啟的話,標記了aduited的service也不會輸出審計日誌
-
定時任務的用法和之前的還是有一些區別.如要體現在runner上.之前的runner要繼承LunaRunnerBase,如果使用hangfire的話要繼承LunaHangfireRunnerBase.同時在run方法裏增加定時任務
public class Runner : LunaHangfireRunnerBase { public override void Run() { RecurringJob.AddOrUpdate<IJobService>(service => service.OutputLog(), Cron.Minutely); } }
啟動的方法還是和之前一樣的使用starter即可.這裏有一點需要註意一下.一定要在調用starter的run方法之前配置好hangfire
GlobalConfiguration.Configuration
這裏推薦使用topshelf之類的框架把程序搞成服務
代碼
和上一版對比的話,這次主要的變更在starter類構造函數中
private Starter(Type runnerType, StarterOption option)
{
Container = new WindsorContainer();
Container.Kernel.ComponentRegistered += (key, handler) =>
{
if (option.DisableAudit) return;
if (handler.ComponentModel.Implementation.IsDefined(typeof(AuditedAttribute), true))
{
handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(AuditingInterceptor)));
}
};
Container.Register(
Classes.FromAssemblyInThisApplication(runnerType.Assembly)
.IncludeNonPublicTypes()
.BasedOn<ITransientDependency>()
.WithServiceAllInterfaces()
.If(type => !type.IsGenericTypeDefinition)
.WithService.Self()
.WithService.DefaultInterfaces()
.LifestyleTransient()
);
Container.Register(
Classes.FromAssemblyInThisApplication(runnerType.Assembly)
.IncludeNonPublicTypes()
.BasedOn<ISingletonDependency>()
.If(type => !type.IsGenericTypeDefinition)
.WithService.Self()
.WithService.DefaultInterfaces()
.LifestyleSingleton()
);
Container.Register(
Classes.FromAssemblyInThisApplication(runnerType.Assembly)
.IncludeNonPublicTypes()
.BasedOn<IInterceptor>()
.If(type => !type.IsGenericTypeDefinition)
.WithService.Self()
.LifestyleTransient()
);
Container.Register(
Component.For<Starter>().Instance(this).LifestyleSingleton()
);
}
新增註冊了ComponentRegistered事件.在組件註冊ioc完成時檢測了組件是否聲明了AuditedAttribute特性,如果有聲明的話就會給組件增加一個攔截器實現審計日誌.
另外就是把starter自己也註冊進了ioc,這其實是為了替換hangfire的JobActivator時使用ioc容器.
public abstract class LunaHangfireRunnerBase : LunaRunnerBase
{
private BackgroundJobServer _backgroundJobServer;
public Starter Starter { get; set; }
public override void Init()
{
base.Init();
JobActivator.Current = new WindsorJobActivator(Starter.Container.Kernel);
_backgroundJobServer = new BackgroundJobServer();
}
public override void Stop()
{
_backgroundJobServer.Dispose();
}
}
可以看到LunaHangfireRunnerBase類的屬性註入了starter.本來考慮構造註入的,但是使用構造註入的話,繼承這個類的runner在代碼上就會看起來不是很純潔,所以放棄了
GitHub: https://github.com/lun3322/Luna.Service
這裏有完整的代碼和例子,沒寫單元測試大家湊合看吧.歡迎star
NuGet1: Install-Package Luna.Service
NuGet2: Install-Package Luna.Service.Nlog
NuGet2: Install-Package Luna.Service.Hangfire
可以看到LunaHangfireRunnerBase類的屬性註入