1. 程式人生 > >可以看到LunaHangfireRunnerBase類的屬性註入

可以看到LunaHangfireRunnerBase類的屬性註入

span 可選 cpp edi oba IT string contain 推薦

接上一篇整合了一個命令行程序的框架我增加了一點功能

aop和定時任務

這次更新主要增加了審計日誌還有集成了hangfire做定時任務

  1. 先來看審計日誌部分,審計日誌主要是使用了Windsor的動態代理功能.每一個添加了Audited特性的方法或者類,在方法被調用時會輸出參數和值.使用時只要在需要審計的service上增加Audited特性即可

    [Audited]
    public class DemoService : LunaServiceBase, IDemoService
    {
        public string GetMessage(string name)
        {
            Logger.Info($"GetMessage {name}"
    ); return "測試"; } public string GetDemo(DemoModel model) { var msg = $"{model.Name}: {model.Age}"; return msg; } }

    同時在start上增加了一個可選參數.目前只有一個設置項,就是是否開啟審計日誌功能.如果不開啟的話,標記了aduited的service也不會輸出審計日誌

  2. 定時任務的用法和之前的還是有一些區別.如要體現在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
    .UseSqlServerStorage("default");

    這裏推薦使用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類的屬性註入