C#訂閱與發佈標準實現 visual studio code .net 開發 設計模式之☞策略模式 C#字符串轉二進制、二進制轉字符串 c# 接口的協變和逆變 c# 使用迭代器來建立可枚舉類型 博客園

C#訂閱與發佈標準實現

 

大概看了下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.
    1. 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.
      1. For example:

 

    1. 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); }
複製代碼
相關文章
相關標籤/搜索