本次將要很大家分享的是一個跨平臺執行的服務外掛 - TaskCore.MainForm,此框架是使用.netcore來寫的,現在netcore已經支援很多系統平臺執行了,所以將以前的Task.MainForm改良成跨平臺的服務共大家使用和相互交流;本來這篇應該分享的是nginx+iis+redis+Task.MainForm構建分散式架構後續文章,但使用.netcore來定義一個服務外掛和跨平臺測試經過讓我既興奮又頭痛,不說了下次再分享分散式後續文章吧;那麼開始今天的分享內容,希望各位多多支援:
. 框架結構介紹及執行效果圖
. 如何生成nuget包和使用開源框架TaskCore.MainForm
. win7和ubuntu16.04執行TaskCore.MainForm的兩種方式和測試截圖(也可認為.netcore專案在win7和ubuntu系統執行的兩種方式)
. 框架程式碼解讀及感悟
下面一步一個腳印的來分享:
. 框架結構介紹及執行效果圖
首先,咋們先來認識下專案原始碼的工程目錄結構如圖:
結構看上去應該夠清晰了,原始碼檔案量也很少,不過的確實現了動態載入程式集dll來執行任務,後面會給出相應的執行截圖,我們再來看下TaskCore.MainForm專案通過vs2015生成之後Bin資料夾中的檔案如圖:
如果安裝了.netcore sdk的話在windows上您只需要上面截圖的檔案就能執行外掛了;再來我們在已經安裝過core sdk的win7系統上執行一下如下命令 dotnet TaskCore.MainForm.dll 就能看到如圖的效果:
沒錯這就是外掛執行起來的效果圖,因為.netcore現目前暫時沒有提供類似於winform那樣的皮膚介面效果,所有隻能通過命令列來做跨平臺執行程式
. 如何生成nuget包和使用TaskCore.MainForm
首先,我們要明確服務是由兩部分構成(TaskCore.MainForm和TaskCore.Plugin);TaskCore.MainForm主要用來執行程式,TaskCore.Plugin用來作為子任務需要繼承的父類外掛;當我們下載TaskCore.MainForm執行包之後(如圖2結構),我們還需要做的就是繼承TaskCore.Plugin.dl中的TPlugin這個類,來重寫自己的任務內容,因此我們新建一個專案取名為:TaskCore.Test,再來我們通過vs2015引用功能直接新增TaskCore.MainForm執行包中的TaskCore.Plugin.dl引用,這個時候會提示一個錯誤:
錯誤意思是沒法載入netcore版本的dll,因此這種直接在vs專案中引用方式新增dll依賴不行,需要通過nuget來新增依賴包(.netcore對類庫的引用目前只能通過nuget來安裝依賴,這個需要注意),所以我這裡把TaskCore.Plugin專案通過 dotnet pack 命令來生成nuget包,然後以便我TaskCore.Test專案中來使用;
如何生成nuget包(win7系統dotnet命令來生成包的過程和下載):
直接在vs中右鍵您需要打包的類庫專案-》選擇"在資源管理器中開啟資料夾"-》這樣就到了您類庫的根目錄,然後退到類庫根目錄的上一級資料夾中-》按住鍵盤”shift"鍵並同時滑鼠右鍵要打包類庫的專案檔案件(我這裡是TaskCore.Plugin資料夾)-》選擇“在此處開啟命令窗體” 這個時候就進入了cmd命令窗體,當然有些朋友直接喜歡直接先cmd再來找對應的磁碟,反正我覺得第一種更快點(不同人不同選擇吧),下面看下操作截圖:
由上圖可以看到,通過命令生成了nupkg檔案,這檔案就是咋們需要在專案中下載安裝的TaskCore.Plugin外掛包;接下來我們來在TaskCore.Test專案中安裝這個外掛如下步奏,右鍵TaskCore.Plugin專案中的“引用”-》選擇“管理nuget程式包”-》然後選擇右上角的這個圖示
-》選擇“Nuget包管理器”-》“程式包源”-》
-》然後選擇新建立的包源,下面設定如圖
這裡的“源(S)”指定的本地路徑就是剛才我們生成的nupkg檔案檔案的磁碟(當然我這裡是吧剛才pack命令生成的檔案複製到了MyNugPackage資料夾中方便測試)-》然後點選”確定“按鈕-》然後在返回到
選擇我們的包源MyNugPackage-》再瀏覽這裡就能看到我們建立的nuget包了
-》選擇並安裝-》好安裝好後我們可以檢視“引用”下面有了如下變化
並且project.json檔案中自動新增了依賴項:
好了到我們的TaskCore.Test專案中就可以使用Task.Plugin包裡面的方法很類等資訊了;
使用TaskCore.MainForm:
由上面的操作TaskCore.Test專案已經安裝了Task.Plugin包,那麼我們在專案中分別建立3個子類並繼承自Task.Plugin包的父類TPlugin並重寫方法TPlugin_Load(),對應檔名稱分別為:BlogsObj.cs,BlogsObj01.cs,BlogsObj02.cs,分別新增入下程式碼內容:
BlogsObj.cs:
1 namespace TaskCore.Test 2 { 3 // This project can output the Class library as a NuGet Package. 4 // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". 5 public class BlogsObj : TPlugin 6 { 7 public BlogsObj() 8 { 9 10 } 11 12 public override void TPlugin_Load() 13 { 14 var sbLog = new StringBuilder(string.Empty); 15 try 16 { 17 sbLog.Append($"這裡是BlogsObj,獲取配置檔案:{this.XmlConfig.Name}"); 18 19 //程式碼塊 20 // 21 22 new WriteLog()._WriteLog($"{DateTime.Now}測試引用nuget包"); 23 24 } 25 catch (Exception ex) 26 { 27 sbLog.Append($"異常資訊:{ex.Message}"); 28 } 29 finally 30 { 31 32 PublicClass._WriteLog(sbLog.ToString(), this.XmlConfig.Name); 33 } 34 } 35 } 36 }
BlogsObj01.cs:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using TaskCore.Plugin; 7 8 namespace TaskCore.Test 9 { 10 // This project can output the Class library as a NuGet Package. 11 // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". 12 public class BlogsObj01 : TPlugin 13 { 14 public BlogsObj01() 15 { 16 17 } 18 19 public override void TPlugin_Load() 20 { 21 var sbLog = new StringBuilder(string.Empty); 22 try 23 { 24 sbLog.Append($"這裡是BlogsObj01,獲取配置檔案:{this.XmlConfig.Name}"); 25 26 //程式碼塊 27 // 28 } 29 catch (Exception ex) 30 { 31 sbLog.Append($"異常資訊:{ex.Message}"); 32 } 33 finally 34 { 35 //Console.WriteLine($"這裡是Blogs,獲取配置檔案:{this.XmlConfig.Name}"); 36 PublicClass._WriteLog(sbLog.ToString(), this.XmlConfig.Name); 37 } 38 } 39 } 40 }
BlogsObj02.cs:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using TaskCore.Plugin; 6 7 namespace TaskCore.Test 8 { 9 // This project can output the Class library as a NuGet Package. 10 // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". 11 public class BlogsObj02 : TPlugin 12 { 13 public BlogsObj02() 14 { 15 16 } 17 18 public override void TPlugin_Load() 19 { 20 //Console.WriteLine($"這裡是Blogs,獲取配置檔案:{this.XmlConfig.Name}"); 21 PublicClass._WriteLog($"這裡是BlogsObj02,獲取配置檔案:{this.XmlConfig.Name}", this.XmlConfig.Name); 22 } 23 } 24 }
好了測試程式碼寫完,咋們生成一下,然後把這個TaskCore.Test.dll拷貝到TaskCore.MainForm執行包中,還需要在PluginXml資料夾中分別建立繼承TPlugin的子類的配置檔案對應的截圖如(注:這裡xml配置檔名稱必須和子類名稱一樣):
配置檔案內容如BlogsObj.xml:
1 <!-- 2 1.xml配置模板 3 2.utf-8檔案 4 3.複製到程式根目錄下面PluginXml資料夾下 5 4.每個任務建議建立和程式dll名稱相同xml配置檔案 6 --> 7 <TaskMain> 8 <!--固定:執行任務時間計時器(分鐘)--> 9 <Timer>1</Timer> 10 <!--固定:任務名稱--> 11 <Name>獲取部落格資訊</Name> 12 <!--固定:賬號--> 13 <UserName></UserName> 14 <!--固定:密碼--> 15 <UserPwd></UserPwd> 16 <!--固定:key--> 17 <ApiKey></ApiKey> 18 <!--固定:key--> 19 <ApiUrl></ApiUrl> 20 <!--固定:是否關閉任務 1:是 0:否--> 21 <CloseTask>0</CloseTask> 22 23 <!--固定:描述--> 24 <Des>獲取部落格資訊</Des> 25 <!--自定義:其他配置資訊--> 26 <Other> 27 <ShenNiuBuXing3>神牛步行3</ShenNiuBuXing3> 28 </Other> 29 </TaskMain>
最後在CrossFiles.xml配置檔案中新增TaskCore.Test.dll檔名稱如:
1 <!-- 2 CrossFiles指定對應任務的dll檔案,必須存在的檔案 3 --> 4 <TaskMain> 5 <File>TaskCore.Test.dll</File> 6 </TaskMain>
好了完成了,我們在windows開發環境上執行看下效果圖:
到這裡我們來簡單總結下怎麼使用TaskCore.MainForm外掛,在自己專案中安裝TaskCore.Plugin的nuget包-》重寫父類TPlugin的TPlugin_Load()方法-》生成自己的專案,拷貝專案的dll到TaskCore.MainForm執行包中-》在執行包中PluginXml資料夾中增加任務子類相同類名的xml檔案並配置如上的配置資訊-》增加CrossFiles.xml中的任務dll檔案配置-》使用命令 dotnet TaskCore.MainForm.dll 執行服務外掛,挺簡單的吧
. win7和ubuntu16.04執行TaskCore.MainForm的兩種方式和測試截圖(也可認為.netcore專案在win7和ubuntu系統執行的兩種方式)
由於環境影響,這裡跨平臺執行測試我只測試win7和ubuntu16.04,其他系統的釋出測試希望朋友們在使用過程中得到結果告知我下謝謝;先來講在win7中執行:
1. 安裝了netcore sdk環境的釋出執行
安裝了sdk後直接可以在cmd命令中 dotnet TaskCore.MainForm.dll 來執行服務,開篇上面講解的示例都是在安裝了sdk後的截圖,服務執行所需要的檔案如圖:
就只有這些檔案(當然程式需要的某些平臺依賴項使用的是安裝的sdk中的檔案,所以看起來很少實際應該包含netcore sdk裡面的檔案才能執行),通過命令執行的效果圖:
2. 未安裝netcore sdk環境的釋出執行
在為安裝sdk平臺上系統上執行才是重點,這樣才可以說是跨平臺;首先,為了更好看效果我們複製一份如圖的兩個檔案到TaskCore.MainForm01資料夾中:
沒錯,只需要這兩個檔案,然後我們需要修改project.json檔案的內容如下注釋的地方:
1 { 2 "version": "1.0.0-*", 3 "buildOptions": { 4 "emitEntryPoint": true 5 }, 6 7 "dependencies": { 8 "Microsoft.NETCore.App": { 9 //"type": "platform", 跨平臺釋出需要註釋 10 "version": "1.0.0" 11 }, 12 "System.IO.FileSystem": "4.0.1", 13 "System.Reflection": "4.1.0", 14 "System.Text.Encoding.CodePages": "4.0.1", 15 "System.Threading.Timer": "4.0.1", 16 "System.Xml.XDocument": "4.0.11", 17 "TaskCore.Plugin": "1.0.0" 18 }, 19 20 "frameworks": { 21 "netcoreapp1.0": { 22 "imports": "dnxcore50" 23 } 24 }, 25 //跨平臺釋出需要新增如下節點 26 "runtimes": { 27 "ubuntu.16.04-x64": { }, //執行在ubuntu.16.04的64位系統 28 "win7-x64": { } //執行在win7的64位系統 29 } 30 }
然後使用cmd分別錄入並回車執行指令 dotnet restore 此時TaskCore.MainForm01資料夾中會自動生成一個project.lock.json檔案(大家注意看下),然後再錄入指令 dotnet publish -r win7-x64 ,可以看到命令窗資訊如:
就表示成功了,並且有返回生成執行檔案的路徑,我們按照路徑找到生成的檔案publish資料夾,裡面沒有PluginXml配置資料夾和配置檔案和測試專案TaskCore.Test.dll,我們為了方便直接複製上面配置好的配置檔案到publish資料夾中如下截圖就是生成的釋出檔案:
沒錯TaskCore.MainForm01.exe這個就是自動生成的執行檔案,然後我們雙擊執行效果圖:
執行成功了,有朋友會問您之前系統不是安裝了sdk麼,這種測試能算麼,我想說的是這個我通過QQ發給qq群裡面的朋友@南宮亦琦(不要怪我貼出了您的暱稱)測試過了,她沒有安裝過sdk的;
ubuntu16.04執行:
1. 安裝了netcore sdk環境的釋出執行
首先,我們需要把在win7上生成的專案複製到ubuntu系統磁碟中(我們使用上面配置好的TaskCore.MainForm包),我這裡採用共享目錄的方式把檔案拷貝到ubuntu系統磁碟上,如圖:
然後,滑鼠右鍵點選空白地方,選擇“在終端開啟”,然後在窗體中錄入如下指令 dotnet TaskCore.MainForm.dll ,能看到如下執行起的結果:
這個命令方式是不是很上面win7上的方式很相同,本來就是一樣的,只要安裝了.netcore sdk這種方式幾乎可以共用
2. 未安裝netcore sdk環境的釋出執行
不安裝sdk環境執行才是咋們需要關注的,下面就來看下怎麼生成再ubuntu系統上能執行的檔案;我們複製一份上面的TaskCore.MainForm01專案到TaskCore.MainForm02中來測試,由於之前我們在講生成win7執行檔案時候,執行了命令 dotnet restore 和 dotnet publish -r win7-x64 命令所以檔案中有project.lock和bin資料夾,為了測試我們需要刪除掉部分檔案,只剩下如圖檔案,這裡需要注意的是之前已經配置過project.xml我們無需在修改了:
然後,分別執行和生成win7執行檔案幾乎相同的命令 dotnet restore 和 dotnet publish -r ubuntu.16.04-x64 不同之處在於生成的檔案存放的位置不同和使用的執行環境不同,執行結果如圖:
publish資料夾中的檔案就是在ubuntu系統執行的檔案,然後我們需要把任務配置資料夾PluginXml和測試專案TaskCore.Test.dll複製到該目錄中,再來咋們通過共享吧TaskCore.MainForm02目錄中的publish複製到ubuntu中;然後我們需要把TaskCore.MainForm02可執行檔案設定下許可權,滑鼠右鍵點選TaskCore.MainForm02可執行檔案,選擇“屬性”,再選擇“許可權”選項卡,勾選“允許作為程式執行”,如圖:
然後,我們右鍵資料夾中空白處,選擇“在終端開啟”,再執行如下命令 ./TaskCore.MainForm02 ,最後看執行效果圖:
好了,釋出在ubuntu系統上執行檔案和執行的步奏就這些,幾乎和win7上相同
. 框架程式碼解讀及感悟
怎麼使用跨平臺TaskCore.MainForm任務框架講解完了,下面來具體看下主要程式碼Program.cs檔案中:
1 namespace TaskCore.MainForm 2 { 3 /// <summary> 4 /// author 神牛步行3 5 /// contact 841202396@qq.com 6 /// des TaskCore.MainForm跨平臺外掛由神牛步行3提供 7 /// </summary> 8 public class Program 9 { 10 11 private static Dictionary<string, MoAssembly> dicTasks = new Dictionary<string, MoAssembly>(); 12 13 public static void Main(string[] args) 14 { 15 //註冊編碼,防止亂碼 16 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 17 18 //初始化程式集檔案 19 _Init(); 20 21 //是否繼續開啟任務,預設沒有待執行任務,不提示 22 if (dicTasks.Count <= 0) { _LoopAlert("是否退出?(Y/N)"); return; } 23 _LoopAlert("是否開始執行任務?(Y / N)"); 24 25 //執行任務 26 foreach (var item in dicTasks.Values) 27 { 28 //使用Task防止異常後相互影響 29 Task.Run(() => 30 { 31 try 32 { 33 34 //建立任務物件 35 var tp = item.Asm.CreateInstance(item.FullName) as TPlugin; 36 if (!string.IsNullOrEmpty(tp.XmlConfig.TpError)) { _Alert($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm")}:{tp.XmlConfig.Name} - 異常資訊:{tp.XmlConfig.TpError}"); } 37 else 38 { 39 40 //timer定時器 41 var timer = new Timer((param) => 42 { 43 var msg = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm")}:{tp.XmlConfig.Name}"; 44 try 45 { 46 var tpObj = param as TPlugin; 47 //是否關閉暫停任務 48 if (tpObj.XmlConfig.CloseTask) { return; } 49 _Alert($"{msg} - 開始執行...{tp.XmlConfig.Timer}分鐘一次"); 50 //任務入口 51 tpObj.TPlugin_Load(); 52 } 53 catch (Exception ex) { _Alert($"{msg} - 異常資訊:{ex.Message}"); } 54 }, tp, 0, 1000 * 60 * tp.XmlConfig.Timer); 55 } 56 57 } 58 catch (Exception ex) 59 { 60 _Alert($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm")}:{item.Name} - 異常資訊:{ex.Message}"); 61 } 62 }); 63 } 64 _LoopAlert("正在監控執行的任務,是否退出?(Y / N)"); 65 } 66 67 /// <summary> 68 /// 初始化程式集檔案 69 /// </summary> 70 private static void _Init() 71 { 72 try 73 { 74 75 _Alert("初始化任務中..."); 76 //獲取檔案 77 var files = PublicClass._GetPluginFile(""); 78 if (files.Length <= 0) { _Alert("未能找到可用的程式集,請檢查配置"); return; } 79 80 //讀取任務檔案 81 _Alert("讀取CrossFiles.xml配置中..."); 82 var baseAddr = Path.Combine(Directory.GetCurrentDirectory(), "PluginXml", "CrossFiles.xml"); 83 var doc = XDocument.Load(baseAddr); 84 var fileables = files.AsEnumerable(); 85 var taskFiles = new List<FileInfo>(); 86 foreach (var item in doc.Root.Nodes()) 87 { 88 var crossFile = item.ToString().ToUpper(); 89 var choiceFiles = fileables.Where(b => crossFile.Contains(b.Name.ToUpper())); 90 if (!choiceFiles.Any()) { continue; } 91 92 taskFiles.AddRange(choiceFiles); 93 } 94 95 //展示檔案資訊 96 _Alert($"待遍歷{taskFiles.Count}個檔案資訊..."); 97 foreach (var item in taskFiles.OrderBy(b => b.CreationTime)) 98 { 99 var asmName = new AssemblyName($"{item.Name.Replace(".dll", "")}"); 100 Assembly sm = Assembly.Load(asmName); 101 if (sm == null) { continue; } 102 var ts = sm.GetTypes(); 103 //判斷特定的任務類,加入任務dic 104 foreach (var t in ts.Where(b => b.Name != "TPlugin" && b.GetMethod("TPlugin_Load") != null)) 105 { 106 107 dicTasks.Add( 108 t.FullName, 109 new MoAssembly 110 { 111 Asm = sm, 112 FullName = t.FullName, 113 Name = t.Name 114 }); 115 } 116 } 117 _Alert($"獲取待執行任務量:{dicTasks.Count}個"); 118 } 119 catch (Exception ex) 120 { 121 _Alert($"異常資訊:{ ex.Message}"); 122 } 123 } 124 125 /// <summary> 126 /// 訊息提醒 127 /// </summary> 128 /// <param name="msg">提示資訊</param> 129 /// <param name="isReadLine">是否需要使用者輸入指令</param> 130 /// <returns>使用者錄入的指令</returns> 131 private static string _Alert(string msg = "神牛步行3-訊息提醒", bool isReadLine = false) 132 { 133 Console.WriteLine(msg); 134 if (isReadLine) { return Console.ReadLine(); } 135 return ""; 136 } 137 138 private static void _LoopAlert(string msg = "是否開始執行任務?(Y/N)") 139 { 140 do 141 { 142 var readKey = _Alert(msg, true); 143 if (readKey.ToUpper().Contains("Y")) { break; } 144 } while (true); 145 } 146 } 147 148 public class MoAssembly 149 { 150 public Assembly Asm { get; set; } 151 public string FullName { get; set; } 152 153 public string Name { get; set; } 154 } 155 }
TPlugin.cs檔案中程式碼:
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Threading.Tasks; 6 using System.Xml.Linq; 7 8 namespace TaskCore.Plugin 9 { 10 /// <summary> 11 /// 外掛基類 12 /// </summary> 13 public class TPlugin : IDisposable 14 { 15 16 public TPlugin() 17 { 18 19 XmlConfig = _InitConfig(); 20 } 21 22 #region 初始化Xml配置檔案 _InitConfig +XmlConfig 23 24 /// <summary> 25 /// xml配置資訊 26 /// </summary> 27 public XmlConfig XmlConfig; 28 29 30 /// <summary> 31 /// 初始化配置資訊 32 /// </summary> 33 /// <param name="configPath">配置檔案對應路徑</param> 34 /// <returns></returns> 35 public virtual XmlConfig _InitConfig(string configPath = "") 36 { 37 XmlConfig config = new XmlConfig(); 38 config.Timer = 1; 39 config.Name = this.GetType().Name; 40 try 41 { 42 43 if (string.IsNullOrEmpty(configPath)) 44 { 45 46 //預設各個dllXml配置 47 var defaultConfigFolder = "PluginXml"; 48 var baseAddr = Directory.GetCurrentDirectory(); 49 configPath = Path.Combine(baseAddr, defaultConfigFolder, config.Name + ".xml"); 50 } 51 52 var doc = XDocument.Load(configPath); 53 config.doc = doc; 54 var taskMain = doc.Root; 55 56 config.Timer = Convert.ToInt32(taskMain.Element(XName.Get("Timer", "")).Value); 57 config.Name = taskMain.Element(XName.Get("Name", "")).Value; 58 config.Des = taskMain.Element(XName.Get("Des", "")).Value; 59 60 config.UserName = taskMain.Element(XName.Get("UserName", "")).Value; 61 config.UserPwd = taskMain.Element(XName.Get("UserPwd", "")).Value; 62 config.ApiKey = taskMain.Element(XName.Get("ApiKey", "")).Value; 63 config.ApiUrl = taskMain.Element(XName.Get("ApiUrl", "")).Value; 64 config.CloseTask = taskMain.Element(XName.Get("CloseTask", "")).Value == "1"; 65 66 } 67 catch (Exception ex) 68 { 69 config.TpError = ex.Message; 70 PublicClass._WriteLog($"{config.Name}初始化配置資訊異常:{ex.Message}", "BaseLog"); 71 throw new Exception(ex.Message); 72 } 73 return config; 74 } 75 #endregion 76 77 #region 初始化-開始載入 _Load 78 79 /// <summary> 80 /// 初始化-開始起 81 /// </summary> 82 public virtual void TPlugin_Load() 83 { 84 85 PublicClass._WriteLog("測試"); 86 } 87 88 #endregion 89 90 #region 釋放資源 91 92 public void Dispose() 93 { 94 95 GC.SuppressFinalize(this);//不需要再呼叫本物件的Finalize方法 96 } 97 98 public virtual void Dispose(Action action) 99 { 100 101 action(); 102 } 103 104 #endregion 105 } 106 107 #region 配置檔案 XmlConfig 108 109 public class XmlConfig 110 { 111 public XmlConfig() 112 { 113 114 } 115 116 /// <summary> 117 /// 定製器時間(分鐘) 118 /// </summary> 119 public int Timer { get; set; } 120 121 /// <summary> 122 /// 執行名稱 123 /// </summary> 124 public string Name { get; set; } 125 126 /// <summary> 127 /// 描述(第一次獲取dll描述,後面獲取xml配置檔案描述) 128 /// </summary> 129 public string Des { get; set; } 130 131 /// <summary> 132 /// 介面賬號 133 /// </summary> 134 public string UserName { get; set; } 135 136 /// <summary> 137 /// 介面密碼 138 /// </summary> 139 public string UserPwd { get; set; } 140 141 /// <summary> 142 /// 介面祕鑰 143 /// </summary> 144 public string ApiKey { get; set; } 145 146 /// <summary> 147 /// 介面地址 148 /// </summary> 149 public string ApiUrl { get; set; } 150 151 /// <summary> 152 /// 是否關閉任務 153 /// </summary> 154 public bool CloseTask { get; set; } 155 156 /// <summary> 157 /// 外掛中錯誤 158 /// </summary> 159 public string TpError { get; set; } 160 161 162 /// <summary> 163 /// xml資訊 164 /// </summary> 165 public XDocument doc { get; set; } 166 } 167 168 #endregion 169 }
具體的說明和邏輯處理程式碼中都有註釋,各位可以詳細看下;這裡要訴說的是該框架主要原理是動態載入任務dll來建立物件,netcore的程式集類Assembly不像framework裡面的Assembly一樣那麼多可以用方法,我這裡用的 Assembly.Load() ,netcore只能載入當前系統根目錄的dll(這裡我花了幾個小時測試,有不同結果的朋友,請及時聯絡我謝謝),框架使用 Task.Run() 方法建立不同任務,實現並行執行的效果,並且各個容易出錯地方使用try...catch來容錯,避免了某個子任務異常後,導致框架全部中斷執行,個人覺得其實還是不錯的是吧;
下面給出幾個不同環境下的壓縮包,以供使用和參考:
TaskCore.MainForm-純檔案 TaskCore.MainForm01 git原始碼地址