一. SignalR中DI思想的應用html
分析解決思路:web
1. 新建Repository類和IRepository接口,裏面聲明SaveMsg方法,用來存儲信息 (PS:便於測試,這裏將信息保存到txt文本文檔中)sql
代碼以下:數據庫
1 public interface IRepository 2 { 3 void SaveMsg(string connectionId, string msg); 4 } 5 public class Repository : IRepository 6 { 7 /// <summary> 8 /// 模擬數據庫插入操做 9 /// 這裏以日誌代替 10 /// </summary> 11 /// <param name="connectionId"></param> 12 /// <param name="msg"></param> 13 public void SaveMsg(string connectionId, string msg) 14 { 15 //此處執行插入數據庫操做 16 FileOperateHelp.WriteFile("/Logs/msg.txt", $"用戶【{connectionId}】發來消息:{msg},時間爲:{DateTime.Now.ToLongDateString()}"); 17 } 18 }
分享一個文件相關操做的工具類FileOperateHelp:性能優化
1 public class FileOperateHelp 2 { 3 #region 01.寫文件(.txt-覆蓋) 4 /// <summary> 5 /// 寫文件(覆蓋源文件內容) 6 /// 文件不存在的話自動建立 7 /// </summary> 8 /// <param name="FileName">文件路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 9 /// <param name="Content">文件內容</param> 10 public static string Write_Txt(string FileName, string Content) 11 { 12 try 13 { 14 Encoding code = Encoding.GetEncoding("gb2312"); 15 string htmlfilename = FileOperateHelp.PathConvert(FileName); 16 //string htmlfilename = HttpContext.Current.Server.MapPath(FileName + ".txt"); //保存文件的路徑 17 string str = Content; 18 StreamWriter sw = null; 19 { 20 try 21 { 22 sw = new StreamWriter(htmlfilename, false, code); 23 sw.Write(str); 24 sw.Flush(); 25 } 26 catch { } 27 } 28 sw.Close(); 29 sw.Dispose(); 30 return "ok"; 31 } 32 catch (Exception ex) 33 { 34 35 return ex.Message; 36 } 37 38 } 39 #endregion 40 41 #region 02.讀文件(.txt) 42 /// <summary> 43 /// 讀文件 44 /// </summary> 45 /// <param name="filename">文件路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 46 /// <returns></returns> 47 public static string Read_Txt(string filename) 48 { 49 50 try 51 { 52 Encoding code = Encoding.GetEncoding("gb2312"); 53 string temp = FileOperateHelp.PathConvert(filename); 54 // string temp = HttpContext.Current.Server.MapPath(filename + ".txt"); 55 string str = ""; 56 if (File.Exists(temp)) 57 { 58 StreamReader sr = null; 59 try 60 { 61 sr = new StreamReader(temp, code); 62 str = sr.ReadToEnd(); // 讀取文件 63 } 64 catch { } 65 sr.Close(); 66 sr.Dispose(); 67 } 68 else 69 { 70 str = ""; 71 } 72 return str; 73 } 74 catch (Exception ex) 75 { 76 77 return ex.Message; 78 } 79 } 80 #endregion 81 82 #region 03.寫文件(.txt-添加) 83 /// <summary> 84 /// 寫文件 85 /// </summary> 86 /// <param name="FileName">文件路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 87 /// <param name="Strings">文件內容</param> 88 public static string WriteFile(string FileName, string Strings) 89 { 90 try 91 { 92 string Path = FileOperateHelp.PathConvert(FileName); 93 94 if (!System.IO.File.Exists(Path)) 95 { 96 System.IO.FileStream f = System.IO.File.Create(Path); 97 f.Close(); 98 f.Dispose(); 99 } 100 System.IO.StreamWriter f2 = new System.IO.StreamWriter(Path, true, System.Text.Encoding.UTF8); 101 f2.WriteLine(Strings); 102 f2.Close(); 103 f2.Dispose(); 104 return "ok"; 105 } 106 catch (Exception ex) 107 { 108 109 return ex.Message; 110 } 111 } 112 #endregion 113 114 #region 04.讀文件(.txt) 115 /// <summary> 116 /// 讀文件 117 /// </summary> 118 /// <param name="FileName">文件路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 119 /// <returns></returns> 120 public static string ReadFile(string FileName) 121 { 122 try 123 { 124 string Path = FileOperateHelp.PathConvert(FileName); 125 string s = ""; 126 if (!System.IO.File.Exists(Path)) 127 s = "不存在相應的目錄"; 128 else 129 { 130 StreamReader f2 = new StreamReader(Path, System.Text.Encoding.GetEncoding("gb2312")); 131 s = f2.ReadToEnd(); 132 f2.Close(); 133 f2.Dispose(); 134 } 135 return s; 136 } 137 catch (Exception ex) 138 { 139 return ex.Message; 140 } 141 } 142 #endregion 143 144 #region 05.刪除文件 145 /// <summary> 146 /// 刪除文件 147 /// </summary> 148 /// <param name="Path">文件路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 149 public static string FileDel(string Path) 150 { 151 try 152 { 153 string temp = FileOperateHelp.PathConvert(Path); 154 File.Delete(temp); 155 return "ok"; 156 } 157 catch (Exception ex) 158 { 159 return ex.Message; 160 } 161 } 162 #endregion 163 164 #region 06.移動文件 165 /// <summary> 166 /// 移動文件 167 /// </summary> 168 /// <param name="OrignFile">原始路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 169 /// <param name="NewFile">新路徑,須要寫上路徑下的文件名,不能單寫路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 170 public static string FileMove(string OrignFile, string NewFile) 171 { 172 try 173 { 174 OrignFile = FileOperateHelp.PathConvert(OrignFile); 175 NewFile = FileOperateHelp.PathConvert(NewFile); 176 File.Move(OrignFile, NewFile); 177 return "ok"; 178 } 179 catch (Exception ex) 180 { 181 return ex.Message; 182 } 183 } 184 #endregion 185 186 #region 07.複製文件 187 /// <summary> 188 /// 複製文件 189 /// </summary> 190 /// <param name="OrignFile">原始文件(web裏相對路徑,控制檯在根目錄下寫)</param> 191 /// <param name="NewFile">新文件路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 192 public static string FileCopy(string OrignFile, string NewFile) 193 { 194 try 195 { 196 OrignFile = FileOperateHelp.PathConvert(OrignFile); 197 NewFile = FileOperateHelp.PathConvert(NewFile); 198 File.Copy(OrignFile, NewFile, true); 199 return "ok"; 200 } 201 catch (Exception ex) 202 { 203 return ex.Message; 204 } 205 } 206 #endregion 207 208 #region 08.建立文件夾 209 /// <summary> 210 /// 建立文件夾 211 /// </summary> 212 /// <param name="Path">相對路徑(web裏相對路徑,控制檯在根目錄下寫)</param> 213 public static string FolderCreate(string Path) 214 { 215 try 216 { 217 Path = FileOperateHelp.PathConvert(Path); 218 // 判斷目標目錄是否存在若是不存在則新建之 219 if (!Directory.Exists(Path)) 220 { 221 Directory.CreateDirectory(Path); 222 } 223 return "ok"; 224 } 225 catch (Exception ex) 226 { 227 return ex.Message; 228 } 229 } 230 #endregion 231 232 #region 09.遞歸刪除文件夾目錄及文件 233 /// <summary> 234 /// 遞歸刪除文件夾目錄及文件 235 /// </summary> 236 /// <param name="dir">相對路徑(web裏相對路徑,控制檯在根目錄下寫) 截止到哪刪除到哪,eg:/a/ 連a也刪除</param> 237 /// <returns></returns> 238 public static string DeleteFolder(string dir) 239 { 240 241 try 242 { 243 string adir = FileOperateHelp.PathConvert(dir); 244 if (Directory.Exists(adir)) //若是存在這個文件夾刪除之 245 { 246 foreach (string d in Directory.GetFileSystemEntries(adir)) 247 { 248 if (File.Exists(d)) 249 File.Delete(d); //直接刪除其中的文件 250 else 251 DeleteFolder(d); //遞歸刪除子文件夾 252 } 253 Directory.Delete(adir, true); //刪除已空文件夾 254 } 255 return "ok"; 256 } 257 catch (Exception ex) 258 { 259 return ex.Message; 260 } 261 } 262 263 #endregion 264 265 #region 10.將相對路徑轉換成絕對路徑 266 /// <summary> 267 /// 10.將相對路徑轉換成絕對路徑 268 /// </summary> 269 /// <param name="strPath">相對路徑</param> 270 public static string PathConvert(string strPath) 271 { 272 //web程序使用 273 if (HttpContext.Current != null) 274 { 275 return HttpContext.Current.Server.MapPath(strPath); 276 } 277 else //非web程序引用 278 { 279 strPath = strPath.Replace("/", "\\"); 280 if (strPath.StartsWith("\\")) 281 { 282 strPath = strPath.TrimStart('\\'); 283 } 284 return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strPath); 285 } 286 } 287 #endregion 288 289 }
2. 採用構造函數注入的方式,在MySpecHub1這個Hub類中進行配置。服務器
代碼以下圖:架構
3. 配置注入代碼,在Startup類中的Configuration方法中,進行依賴注入代碼的配置。併發
代碼以下:app
每當須要建立MySpecHub1實例,SignalR 將調用此匿名函數。
GlobalHost.DependencyResolver.Register(typeof(MySpecHub1), () => new MySpecHub1(new Repository()));負載均衡
4. 在羣發接口中進行SaveMsg方法的調用進行測試。
5. 測試結果:
二. 基於SQLServer或Redis進行部署
下面以SQLServer爲例簡單的配置一下。
1. 經過Nuget下載程序集:Microsoft.AspNet.SignalR.SqlServer
2. 在SQLServer中新建一個數據庫,好比 SignalRDB,不須要建立任何表,由於程序運行時,會自動生成所需表
3. 在Startup中配置映射數據庫,代碼以下:
1 public class Startup 2 { 3 public void Configuration(IAppBuilder app) 4 { 5 app.UseCors(CorsOptions.AllowAll).MapSignalR(); 6 //四. 性能優化 7 // 1. SQLServer版本(跨服務器通訊代碼配置) 8 string sqlConnectionString = "data source=localhost;initial catalog=SignalRDB;persist security info=True;user id=sa;password=123456;"; 9 GlobalHost.DependencyResolver.UseSqlServer(sqlConnectionString); 10 11 } 12 }
以上3步,已經實現了不一樣地址間SignalR間的通信,配置很是簡單,內部複雜實現微軟已經給實現好了,那麼下面咱們簡單的部署一下,分別部署在1001 和 1002 端口下,進行通信。
PS:補充Redis的配置
1. 經過Nuget下載程序集:Microsoft.AspNet.SignalR.Redis
2. 代碼配置:GlobalHost.DependencyResolver.UseRedis("127.0.0.1", 6379, "123456", "mykey");
截止到此處Signalr系列入門已經所有更新完成,再深刻的須要小夥伴們自行研究了,原計劃的項目案例因爲剝離代碼實在是太耗時間了,暫時擱置,後面有時間在補充,下一步會給該系列作一個目錄就完全告一段落。
!