大概看了下C#官方提供的IObservable接口以及IObserver接口來實現發佈和訂閱,寫的很標準,頗有表明性,作下筆記,之後要是項目須要用到發佈訂閱再基於本身的需求改:html
public class BaggageInfo { private int flightNo; private string origin; private int location; internal BaggageInfo(int flight, string from, int carousel) { this.flightNo = flight; this.origin = from; this.location = carousel; } public int FlightNumber { get { return this.flightNo; } } public string From { get { return this.origin; } } public int Carousel { get { return this.location; } } } /// /// 發佈者 /// public class BaggageHandler : IObservable<BaggageInfo> { private List<IObserver<BaggageInfo>> observers; private List<BaggageInfo> flights; public BaggageHandler() { observers = new List<IObserver<BaggageInfo>>(); flights = new List<BaggageInfo>(); } public IDisposable Subscribe(IObserver<BaggageInfo> observer) { // Check whether observer is already registered. If not, add it if (! observers.Contains(observer)) { observers.Add(observer); // Provide observer with existing data. foreach (var item in flights) observer.OnNext(item); } return new Unsubscriber<BaggageInfo>(observers, observer); } // Called to indicate all baggage is now unloaded. public void BaggageStatus(int flightNo) { BaggageStatus(flightNo, String.Empty, 0); } public void BaggageStatus(int flightNo, string from, int carousel) { var info = new BaggageInfo(flightNo, from, carousel); // Carousel is assigned, so add new info object to list. if (carousel > 0 && ! flights.Contains(info)) { flights.Add(info); foreach (var observer in observers) observer.OnNext(info); } else if (carousel == 0) { // Baggage claim for flight is done var flightsToRemove = new List<BaggageInfo>(); foreach (var flight in flights) { if (info.FlightNumber == flight.FlightNumber) { flightsToRemove.Add(flight); foreach (var observer in observers) observer.OnNext(info); } } foreach (var flightToRemove in flightsToRemove) flights.Remove(flightToRemove); flightsToRemove.Clear(); } } public void LastBaggageClaimed() { foreach (var observer in observers) observer.OnCompleted(); observers.Clear(); } } internal class Unsubscriber<BaggageInfo> : IDisposable { private List<IObserver<BaggageInfo>> _observers; private IObserver<BaggageInfo> _observer; internal Unsubscriber(List<IObserver<BaggageInfo>> observers, IObserver<BaggageInfo> observer) { this._observers = observers; this._observer = observer; } public void Dispose() { if (_observers.Contains(_observer)) _observers.Remove(_observer); } } /// /// 訂閱者 /// public class ArrivalsMonitor : IObserver<BaggageInfo> { private string name; private List<string> flightInfos = new List<string>(); private IDisposable cancellation; private string fmt = "{0,-20} {1,5} {2, 3}"; public ArrivalsMonitor(string name) { if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("The observer must be assigned a name."); this.name = name; } public virtual void Subscribe(BaggageHandler provider) { cancellation = provider.Subscribe(this); } public virtual void Unsubscribe() { cancellation.Dispose(); flightInfos.Clear(); } public virtual void OnCompleted() { flightInfos.Clear(); } // No implementation needed: Method is not called by the BaggageHandler class. public virtual void OnError(Exception e) { // No implementation. } // Update information. public virtual void OnNext(BaggageInfo info) { bool updated = false; // Flight has unloaded its baggage; remove from the monitor. if (info.Carousel == 0) { var flightsToRemove = new List<string>(); string flightNo = String.Format("{0,5}", info.FlightNumber); foreach (var flightInfo in flightInfos) { if (flightInfo.Substring(21, 5).Equals(flightNo)) { flightsToRemove.Add(flightInfo); updated = true; } } foreach (var flightToRemove in flightsToRemove) flightInfos.Remove(flightToRemove); flightsToRemove.Clear(); } else { // Add flight if it does not exist in the collection. string flightInfo = String.Format(fmt, info.From, info.FlightNumber, info.Carousel); if (! flightInfos.Contains(flightInfo)) { flightInfos.Add(flightInfo); updated = true; } } if (updated) { flightInfos.Sort(); Console.WriteLine("Arrivals information from {0}", this.name); foreach (var flightInfo in flightInfos) Console.WriteLine(flightInfo); Console.WriteLine(); } } } using System; using System.Collections.Generic; public class Example { public static void Main() { //發佈者 BaggageHandler provider = new BaggageHandler(); // 訂閱者 ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1"); // 訂閱者 ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit"); // 發佈 provider.BaggageStatus(712, "Detroit", 3); //訂閱 observer1.Subscribe(provider); provider.BaggageStatus(712, "Kalamazoo", 3); provider.BaggageStatus(400, "New York-Kennedy", 1); provider.BaggageStatus(712, "Detroit", 3); observer2.Subscribe(provider); provider.BaggageStatus(511, "San Francisco", 2); provider.BaggageStatus(712); observer2.Unsubscribe(); provider.BaggageStatus(400); provider.LastBaggageClaimed(); } }
visual studio code .net 開發
Visual Studio確實是至關好用,各類簡化操做什麼的簡直不要太舒服。但其容量太大,有時不是很方便,因此今天簡單介紹一下另外一個工具--Visual Studio Code.linux
雖然相比於老大哥Visual Studio,VS Code有不少功能不完善,但它也更靈活輕便。而且VS Code還在不斷的更新當中,目前的最新版本是18年11月更新的1.30版本,包含了 多行搜索改進 等內容。git
下面以.Net開發爲例:github
不一樣於Visual Studio,在VS Code上進行.Net開發你須要安裝一些插件,點擊左側邊欄箭頭這個位置搜索web
安裝插件 C# (C# for Visual Studio Code (powered by OmniSharp)) (必須)算法
-
Lightweight development tools for .NET Core.
-
-
Great C# editing support, including Syntax Highlighting, IntelliSense, Go to Definition, Find
-
All References, etc.
-
Debugging support for .NET Core (CoreCLR). NOTE: Mono debugging is not supported. Desktop CLR debugging has limited support.
-
Support for project.json and csproj projects on Windows, macOS and Linux.
安裝插件 NuGet Package Manager (推薦,方便搜索,安裝Nuget包) (推薦)數據庫
-
Search the NuGet package repository for packages using either (partial or full) package name or another search term.
-
Add PackageReference dependencies to your .NET Core 1.1+ .csproj or .fsproj files from Visual Studio Code's Command Palette.
-
Remove installed packages from your project's .csproj or .fsproj files via Visual Studio Code's Command Palette.
-
Handles workspaces with multiple .csproj or .fsproj files as well as workspaces with single .csproj/.fsproj files.
-
-
-
For example:
-
-
-
Ctrl + P Then Shift + > Choose "Nuget Package Manager: Add Package". Then Input the keyword about the Nuget Package. Finally, Choose the project you want to add the Nuget package.
VSCode 安裝插件後通常須要從新激活以啓用插件。因爲VSCode自己不斷更新,對於某些版本的VSCode可能須要重啓應用,才能激活插件。
在VSCode中運行調試前,須要在.vscode路徑下額外配置兩個文件 launch.json 和 tasks.json, 來告訴vscode如何啓動項目。
Launch.json:編程
{ // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md "version": "0.2.0", "configurations": [ { "name": ".NET Core Launch (web)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. "program": "${workspaceRoot}/MyABP.Web/bin/Debug/netcoreapp2.1/MyABP.Web.dll", "args": [], "cwd": "${workspaceRoot}/MyABP.Web", "stopAtEntry": false, "internalConsoleOptions": "openOnSessionStart", "launchBrowser": { "enabled": true, "args": "${auto-detect-url}", "windows": { "command": "cmd.exe", "args": "/C start ${auto-detect-url}" }, "osx": { "command": "open" }, "linux": { "command": "xdg-open" } }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" }, "sourceFileMap": { "/Views": "${workspaceRoot}/Views" } }, { "name": ".NET Core Attach", "type": "coreclr", "request": "attach", "processId": "${command:pickProcess}" } ] }
若是你第一次運行某個項目,你須要確保全部引用的內容都存在,如上面的MyAbp.Web.dll文件.另外,這些配置不是固定不變的,你能夠根據你的須要來進行不一樣的配置。json
如上面c#
"preLaunchTask": "build" 指定了你的項目在launch以前要先進行build操做。
又如
"env": { "ASPNETCORE_ENVIRONMENT": "Development" }
指定了你要在「哪一個環境」下啓動你的項目。(實際上一個項目會有多種環境的配置,舉個例子 appsetings.Development.json 和 appseting.QA.json用於區分不一樣環境的配置,若是發如今QA環境出現了問題本地不能重現時,天然須要切換到目標環境來進行調試)
Tasks.json:
{ "version": "0.1.0", "command": "dotnet", "isShellCommand": true, "args": [], "tasks": [ { "taskName": "build", "args": [ "${workspaceRoot}/MyABP.Web/MyABP.Web.csproj" ], "isBuildCommand": true, "problemMatcher": "$msCompile" } ] }
這裏能夠配置一下Task,如上面的
"preLaunchTask": "build" 具體的任務流程即在這裏配置。
這裏除去筆者使用的Web項目的配置外,固然還能夠有多種其餘項目應用的配置,如
這些配置完成以後,點擊如圖所示這個位置進入調試面板,而後點擊上面的綠色三角就能夠開始你的調試啦
/ **************************************************分割線*************************************************************/
vscode下經常使用DotNet命令
dotnet所使用的命令均可以使用 --help的方式來查看更詳細的用法。
如dotnet --help
在項目開發過程當中,經常使用的命令有
dotnet new
用於新建內容,dotnet提供了許多模板,如Console Application, Class Library等等。
使用dotnet new時須要注意新建的項目是基於.Net Framework仍是基於.NetCore.
可使用 -f 來指定.
dotnet restore
主要是尋找當前目錄下的項目文件(project.json),而後利用NuGet庫還原整個項目的依賴庫,而後遍歷每一個目錄,生成項目文件,繼續還原該項目文件中的依賴項 --CSDN yangzhenping
如下命令不解釋了,可使用 --help 查看具體用法
dotnet build
dotnet run
dotnet publish
設計模式之☞策略模式
策略模式:它定義了算法家族,分別封裝起來,讓它們之間能夠相互替換,此模式讓算法的變化,不會影響到使用算法的客戶。
今天來經過一個案例,來說一下商場的促銷案例。通常商場會有那些活動呢?總結了下,通常會有這3種促銷活動:一、正常收費;二、打折;三、滿多少返多少
面向對象的編程,並非類越多越好,類的劃分是爲了封裝,但分類的基礎是抽象,具備相同屬性和功能的抽象集合纔是類。
現金收費抽象類:
1 abstract class CashSupper //現金收費抽象類 2 { 3 public abstract double acceptCash(double money);//現金收取類的抽象方法,收取現金,參數爲原價,返回爲當前價 4 }
正常收費子類:
1 class CashNormal : CashSupper //正常收費子類 2 { 3 public override double acceptCash(double money) 4 { 5 return money; 6 } 7 }
打折收費子類:
1 class CashRebate : CashSupper //打折收費子類 2 { 3 private double moneryRebate = 1d; 4 public CashRebate(string moneryRebate) 5 { 6 this.moneryRebate = double.Parse(moneryRebate); //打折收費,初始化時,必需要輸入折扣率,如八折,就是0.8 7 } 8 public override double acceptCash(double money) 9 { 10 return money * moneryRebate; 11 } 12 }
返利收費子類:
1 class CashReturn : CashSupper 2 { 3 private double moneryCondition = 0.0d; 4 private double MoneryReturn = 0.0d; 5 public CashReturn(string moneryCondition,string moneryReturn) //返利收費,初始化時必需要輸入返利條件和返利值,好比滿300返100,則moneryCondition=300,moneryReturn=100 6 { 7 this.moneryCondition =double.Parse(moneryCondition); 8 this.MoneryReturn = double.Parse(moneryReturn); 9 } 10 public override double acceptCash(double money) 11 { 12 double result = money; 13 if (money>=moneryCondition) //若大於返利條件,則須要減去返利值 14 { 15 result = money - Math.Floor(money / moneryCondition) * MoneryReturn; 16 } 17 return result; 18 } 19 }
現金收費工廠類:
1 class CashFactory 2 { 3 public static CashSupper createCashAccept(string type) 4 { 5 CashSupper cs = null; 6 switch (type) 7 { 8 case "正常收費": 9 cs = new CashNormal(); 10 break; 11 case "滿300反100": 12 CashReturn cr1 = new CashReturn("300","100"); 13 cs = cr1; 14 break; 15 case "打8折": 16 CashRebate cr2 = new CashRebate("0.8"); 17 cs = cr2; 18 break; 19 } 20 return cs; 21 } 22 }
CashContext類:
1 class CashContext 2 { 3 private CashSupper cs=null; //聲明一個CashSuper 4 public CashContext(string type) //表示收費的類型 5 { 6 switch (type) 7 { 8 case "正常收費": 9 CashNormal cs0 = new CashNormal(); 10 cs = cs0; 11 break; 12 case "滿300返100": 13 CashReturn cr1 = new CashReturn("300","100"); 14 cs = cr1; 15 break; 16 case "打8折": 17 CashRebate cr2 = new CashRebate("0.8"); //將實例化具體策略的過程由客戶端轉移到Context類中。簡單工廠的引用 18 cs = cr2; 19 break; 20 } 21 } 22 public double GetResult(double Money) 23 { 24 return cs.acceptCash(Money); //根據收費策略的不一樣,得到計算結果 25 } 26 }
界面:
調用:
1 double total = 0.0d; //用戶總計 2 private void btnOk_Click(object sender, EventArgs e) 3 { 4 CashContext cc = new CashContext(cmbType.SelectedItem.ToString()); 5 double totalPrices = 0d; 6 totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text)*Convert.ToDouble(txtNumber.Text)); //經過對Context的GetResult方法的調用,能夠獲得收取費用的結果,讓具體算法與客戶進行隔離 7 total = total + totalPrices; 8 listBox1.Items.Add("單價:"+txtPrice.Text+"數量:"+txtNumber.Text+" "+cmbType.SelectedItem+"合計:"+totalPrices.ToString()); 9 label5.Text = total.ToString(); 10 }
C#字符串轉二進制、二進制轉字符串
最近公司要作一個操做日誌的模塊,若是將操做日誌以字符串的形式存到後臺數據庫,很是浪費內存,不可取,特地寫了字符串與二進制相互轉換的函數。
一、字符串轉二進制
1 private string StringToBinary(string str) 2 { 3 byte[] data = Encoding.Unicode.GetBytes(str); 4 StringBuilder sb = new StringBuilder(data.Length*8); 5 foreach (byte item in data) 6 { 7 sb.Append(Convert.ToString(item,2).PadLeft(8,'0')); 8 } 9 return sb.ToString(); 10 }
二、二進制轉字符串
1 private string BinaryToString(string str) 2 { 3 System.Text.RegularExpressions.CaptureCollection cs = System.Text.RegularExpressions.Regex.Match(str,@"([01]{8})+").Groups[1].Captures; 4 byte[] data = new byte[cs.Count]; 5 for (int i = 0; i < cs.Count; i++) 6 { 7 data[i] = Convert.ToByte(cs[i].Value,2); 8 } 9 return Encoding.Unicode.GetString(data,0,data.Length); 10 }
下面隨便寫了一條Sql語句,便於測試二者是否轉換成功?
轉碼成功!
c# 接口的協變和逆變
若是派生類只是用於輸出值,那麼這種結構化的委託有效性之間的常數關係叫作協變
就是建立一個派生類委託對象 讓派生類賦值給基類對象 協變關鍵字out
對指望傳入基類時容許傳入派生對象的特性叫逆變 逆變關鍵字in
看一下實現代碼
class Animal { public string Name; } class Dog:Animal { } interface Im<out T>//協變 { T GetT(); } class MyClass<T> : Im<T> { public T[] item = new T[2]; public T GetT() { return item[0]; } } class Program { static void DoSomething(Im<Animal> im) { Console.WriteLine(im.GetT().Name); } static void Main(string[] args) { MyClass<Dog> myClass = new MyClass<Dog>(); myClass.item[0] = new Dog() { Name = "AVT" }; Im<Animal> ANIMAL = myClass; DoSomething(myClass); } }
c# 使用迭代器來建立可枚舉類型
class Program { public IEnumerator<string> GetEnumerator() { IEnumerable<string> my = BlackAndWhite(); return my.GetEnumerator(); } public IEnumerable<string> BlackAndWhite() { yield return "black"; yield return "gray"; yield return "white"; } static void Main(string[] args) { Program program = new Program(); foreach (var item in program) { Console.WriteLine(item); } foreach (var item in program.BlackAndWhite()) { Console.WriteLine(item); } } }
c# 建立,加載,修改XML文檔
using System.Xml.Linq;
static void Main(string[] args) { XDocument xDocument = new XDocument(new XElement("mployess", //建立跟元素 new XElement("name", "a"),new XElement("name","b")));//建立元素 xDocument.Save("地址"); XDocument empole = XDocument.Load("地址");//加載xml 文檔 能夠保證修改 Console.WriteLine(empole); }