由來
對於喜歡開發的我經常會寫一些小工具,這些小工具多以功能為主,不要求漂亮、個性化的UI。但起碼要保證使用方便,因此最基本的功能要有:
- GUI(圖片用戶界面)
- 程序配置的保存與讀取(讓用戶在GUI上操作要方便)
- 用戶使用習慣的自動記錄(例如:上次關閉時窗口位置及大小等)
- 程序崩潰捕獲及上報
- 實時顯示運行日志(當前執行到哪步了,輸出結果是什么)
- 多線程管理及調度框架
如果每個工具都要COPY一遍以上功能的代碼以后維護起來是個大坑,封裝成庫調用呢?那每個工具都要寫一遍組裝UI組件的代碼。
仔細想一下,其實我要寫的就是一款小工具,它以實現功能為主。
那么我就需要有一個開發框架,它可以讓我只專注於功能(業務)的實現,簡化UI相關的編碼,最好是能用一行代碼就實現一個UI功能,這個開發框架現在寫好了我給它取名為TaskHosting
TaskHosting初識
先來張截圖看看它長什么樣~_~
TaskHosting界面中大部分UI都是可以自定義的,大部分情況下只需要2-3行C#代碼就可以定制一部分UI功能,如果你不會WPF也可以用WinForms定制里面的UI(通過WindowsFormsHost)。
當然我們的目標是不關心UI,專注於功能實現,讓我們來看下如何使用它。
首先從Hello Word開始:
- 首先要創建一個類庫項目,然后引用TaskHosting框架相關類庫
- 項目屬性 > 調試 > 啟動操作 > 選擇【啟動外部程序】,路徑填寫TaskHosting.exe的路徑
- 創建一個【任務】類 HelloWordTask.cs,代碼如下(現在先不用明白什么意思,后面會有介紹):
1 [Task("Hello Word", IsMutilThread = true, ConfigType = typeof(Config))] 2 class HelloWordTask : Mondol.TaskHosting.Task 3 { 4 private readonly Config _cfg; 5 private readonly IImmediateLogger _immediateLogger; 6 7 public HelloWordTask(Config cfg, IImmediateLogger immediateLogger) 8 { 9 _cfg = cfg; 10 _immediateLogger = immediateLogger; 11 } 12 13 public override void OnRun() 14 { 15 _immediateLogger.Info($"設置1的值為: { _cfg.Setting1}"); 16 _immediateLogger.Info($"設置2的值為: { _cfg.Setting2}"); 17 } 18 } 19 }
- 創建一個【任務】的配置類 Config.cs,代碼如下:
1 class Config : Mondol.Configuration, ITaskConfig 2 { 3 private readonly IAppEnvironment _appEnv; 4 5 public Config(IAppEnvironment appEnv) 6 { 7 this._appEnv = appEnv; 8 } 9 10 protected override string GetConfigurationFilePath() 11 { 12 return Path.Combine(_appEnv.GetPluginDataBasePath(GetType().Assembly), "HelloWord.Config.json"); 13 } 14 15 [Category("基本設置"), DisplayName("設置1"), Description("程序設置1,存儲 string 類型的設置")] 16 public string Setting1 17 { 18 get 19 { 20 return GetProperty(nameof(Setting1), "我是設置1的默認值"); 21 } 22 set 23 { 24 SetProperty(nameof(Setting1), value); 25 } 26 } 27 28 [Category("基本設置"), DisplayName("設置2"), Description("程序設置2,存儲 int 類型的設置")] 29 public int Setting2 30 { 31 get 32 { 33 return GetProperty(nameof(Setting2), 5); 34 } 35 set 36 { 37 SetProperty(nameof(Setting2), value); 38 } 39 } 40 }
運行程序,效果如下:
怎么樣,是不是很簡單?
有什么功能
目前TaskHosting有如下功能:
- 強大的日志功能
- 輸出到UI中的即時日志也可以存到文件、數據庫、甚至遠程服務器
- 程序崩潰自動將異常記錄日志
- 即時日志可按日志級別(跟蹤、調試、信息、警告、錯誤、致命)過濾顯示
- 可用專用的文件日志分析工具
- 方便的配置存取
- 每個【任務】都可以有自己的配置文件
- 配置文件自動讀取、自動保存
- 配置項可限制數據類型、支持拖拽
- 配置項可加詳細描述
- 自動記錄使用習慣
- 重新打開軟件會恢復上次選擇的【任務】、窗口大小、位置等
- 崩潰捕獲及上報
- 自動捕獲未處理異常,並顯示友好錯誤處理窗口
- 未處理異常可自動上報服務器、發郵件或由用戶處理
- 多線程調度框架
- 經過優化的線程調度框架、最大化利用系統資源
- 【任務】可決定是否啟用多線程
- 更多特性還在完善中。。。
以上功能均可靈活的自定義,TaskHosting的目標 - 簡潔而不簡單
設計概念
TaskHosting是一個【任務】的管理器(繼承自Mondol.TaskHosting.Task的類就是一個任務),每一個【任務】對應一個功能,例如:網址采集任務、數據同步任務等。
【任務】的類來自於你編寫的類庫項目(下稱插件),每一個插件可以包含多個任務。
參考上面的HelloWordTask類,它繼承了Mondol.TaskHosting.Task所以它是一個任務,將來會顯示在【任務:】列表中。
你可以用Task屬性來指定任務的名稱、是否支持多線程、配置類類型等
無處不在的依賴注入
依賴注入是一個很簡單的概念,例如:ClassA依賴於ClassB,ClassB又依賴於ClassC,傳統的硬編碼方式是先分別new出ClassB、ClassC才能new ClassA。
依賴注入框架會管理這種依賴關系,使用時無需關心誰依賴誰,只需要告訴框架我需要ClassA的實例,它就會自動幫你創建出來。
詳細依賴注入的概述網上有很多介紹文章,大家找一下就好了。
TaskHosting采用了Autofac來管理模塊間的依賴關系,TaskHosting支持3種類型注冊的方式:
- 編碼注冊
//相當於程序的Main方法所屬類(后面會詳細介紹) internal class Initializer : IInitializer { public void ConfigureServices(ContainerBuilder builder) { //Autofac的方式注冊 builder.RegisterType<Config>().AsSelf(); } }
- 屬性注冊
//通過屬性注入,可指定是否單例、作用域 [Injection(AsType = typeof(Config), IsSingleInstance = true, Scope= InjectionScope.Running)] class Config { //類實現... }
- 自動注冊
所有實現了ITaskConfig接口的類都會自動注冊為單例,例如:
class Config : Mondol.Configuration, ITaskConfig { //類實現... }
除了插件自己注冊的類型外,框架還會注冊一些接口給插件使用,例如:
- IAppEnvironment //APP環境
- IEventManager //事件管理器
- IImmediateLogger //即時日志輸出接口
更多接口請參見Mondol.TaskHosting.Abstractions.dll程序集,這個程序集里全是接口定義,里面的接口將來都可以通過依賴注入獲取到
小結
以上簡單的介紹了TaskHosting的概念及基本用法,其目的就是讓你可以更專注於功能業務的開發,而無需過多關心UI實現細節。
后續會詳細介紹一些高級的使用方法及示例
使用中如有什么意見或問題歡迎隨時反饋給我Q46029811
以上提到的示例代碼:單擊下載