天天看點

C#進階程式集反射隐式類型:匿名類型:擴充方法:初始化器:XML(可擴充标記語言)Xml讀寫(Dom XmlDocumnet demo):深拷貝與淺拷貝Attribute特性(attribute)自定義特性(核心 反射):

程式集

程式集概念:

程式集是.net中的概念。

.net中的dll與exe檔案都是程式集。(exe與dll的差別(exe有程式主入口,可以執行,dll沒有主入口,不可運作))

程式集(Assembly),可以看做是一堆相關類打一個包,相當于java中的jar包(*)

程式集的内容:

程式集包含:

類型中繼資料(描述在代碼中定義的每一類型和成員,二進制形式)

程式集中繼資料(程式集清單、版本号、名稱等)

IL代碼(這些都被裝在exe或dll中)

資源檔案

每個程式集都有自己的名稱、版本等資訊。這些資訊可以通過AssemblyInfo.cs檔案來自己定義

程式集的好處:

程式中隻引用必須的程式集,減小程式的尺寸。

程式集可以封裝一些代碼,隻提供必要的通路接口。

添加程式集引用:

添加路徑、項目引用、GAC(全局程式集緩存)(了解)

不能循環添加引用

在c#中添加其他語言編寫的dll檔案的引用。(參考P/Invoke,在.net中調用非程式集的dll)

反射

反射:

就是動态擷取程式集中的中繼資料來操作類型

反射中的一個重要的類(type):

擷取type的來那個中方法:

    通過類獲得Type:Type t = typeof(Person)

通過對象獲得類的Type:Type t = p.GetType()

Type類的一些常用驗證方法:

        bool IsAssignableFrom(Type c):(直譯:是否可以從c指派)判斷目前的類型的變量是不是可以接受c類型變量的指派。

bool IsInstanceOfType(object o):判斷對象o是否是目前類的執行個體(目前類可以是o的類、父類、接口)

bool IsSubclassOf(Type c):判斷目前類是否是類c的子類。類的事,沒有接口的事。

IsAbstract,判斷是否為抽象的,含接口

關于Assembly的介紹:

加載程式集方法:

    Assembly asm=Assembly.LoadFile(“c:\abc.dll”);

調用Assembly的GetExportedTypes方法可以得到Assembly中定義的所有的public類型

調用Assembly的GetTypes()方法可以得到Assembly中定義的所有的類型

調用Assembly的GetType(name)方法可以得到Assembly中定義的全名為name的類型資訊

動态建立對象:

Activator.CreateInstance(Type t)會動态調用類的無參構造函數建立一個對象,傳回值就是建立的對象,如果類沒有無參構造函數就會報錯

GetConstructor(參數清單);//這個是找到帶參數的構造函數

動态調用的一些成員:

      MemberInfo類  抽象類,有很多子類,下面講的類都繼承自它,擷取程式內建員的相關資訊(類型、方法、事件、字段和屬性)

PropertyInfo 擷取屬性

主要成員:CanRead、CanWrite、PropertyType屬性類型;SetValue、GetValue:讀取值,設定值,第一個參數是執行個體對象,因為set、get要針對具體執行個體,最後一個參數null。     pInfo.SetValue(p1, 30, null)

MethodInfo  擷取方法

MethodInfo都是和具體對象不相關的,是以需要第一個參數指定要執行的對象。

FieldInfo     擷取字段

EventInfo     擷取事件

反射若幹場景(了解):

    1.插件機制,保證了程式的封裝性,同時提高了程式的可擴充性。

2.asp.net中根據使用者通路的頁面動态建立頁面對象,比如通路Index.aspx,則根據通路的頁面名稱Index,通過反射動态建立該類型的對象。(在aspx頁面中執行<%=System.Reflection.Assembly.GetExecutingAssembly().Location %>,檢視dll中頁面生成的的類名)

3.資料通路層中使用工廠模式時,根據配置檔案動态建立資料通路層對象。

4.各種架構中,修改配置檔案即可實作不同效果,都用到了反射。

5.通路類中的私有成員

6.各種需要動态建立類對象的場景都可以使用

隐式類型:

    var關鍵字(在編譯時已經能确定變量的類型了。并不是弱類型。)

var i = 5;//int

var j = 23.56;//double

var k = "C Sharp";//string

var x;//錯誤

var y = null;//錯誤

var z = { 1, 2, 3 };//錯誤  var z=new[] {1,2,3};//正确。

var 強類型.根據後面的值自動推斷類型,編譯時把推斷的類型替換掉var

隻是友善程式員使用而已。

不能作為類成員的類型、不能用作方法的參數,傳回值。(隻能用作局部變量的類型推斷)

匿名類型:

    var p1 = new { Id = 1, Name = "YJingLee", Age = 22 };//屬性也不需要申明

var p2 = new { Id = 2, Name = "XieQing", Age = 25 };

數組

var intArray = new[] { 2, 3, 5, 6 };

var strArray = new[] { "Hello", "World" };

var objArray= new[] { new { Name = "YJingLee", Age = 22 }, new { Name = "XieQing", Age = 25 } };

擴充方法:

      将擴充方法放到一個單獨的類中,類聲明為static(靜态類),方法是靜态方法,并且在第一個string上增加this。哇,string類“增加”擴充方法方法了,這隻是假象,本質上仍然是靜态方法,隻不過C#提供了這樣一個便利給大家,擴充方法内部不能調用被擴充類的私有、protected的東西。

聲明擴充方法的步驟:類必須是static,方法是static,第一個參數是被擴充的對象,前面标注this(this 資料類型 參數名)。使用擴充方法的時候必須保證擴充方法類已經在目前代碼中using

初始化器:

    對象初始化器

Student stu= new Student(){ Id = 1, Name = "YJingLee", Age = 22 };

更友善給對象指派,在構造函數之後執行指派,看IL代碼。

集合初始化器

List<int> num = new List<int> (){ 0, 1, 2, 6, 7, 8, 9 };

List< Student > stus= new List< Student >

{ new Student{Id=1,Name="YJingLee",Age=22},

new Student{Id=2,Name="XieQing",Age=25}, };

XML(可擴充标記語言)

Xml文法特點:

  1. 嚴格區分大小寫
  2. 有且隻能有一個根節點
  3. 有開始标簽必須有結束标簽
  4. 屬性必須使用雙引号
  5. 沒有預定義标簽與html不一樣
  6. 文檔聲明:<?xml version="1.0" encoding="utf-8"?>
  7. 注釋:<!-- -->
  8. CDATA區:即原意文本-<![CDATA[…]]>
  9. 注意編碼問題,文本檔案實際編碼要與文檔聲明中的編碼一緻。

Xml讀寫(Dom XmlDocumnet demo):

l  兩種方式,推薦使用第二種:

n  XmlDocument

n  XDocument、(XElement、XAttribute)

   XmlDocument xdoc=new XmlDocument();

    //文檔聲明

    xdoc.AppendChild(xdoc.CreateXmlDeclaration("1.0","utf-8",null));

    //添加根節點

    XmlElement xeroot=xdoc.CreateElement("Order");

       xdoc.AppendChild(xeroot);

      XmlElement xeCust =xdoc.CreateElment("CustomerName");

      xeCust.InnerText="老楊";

      xeroot.AppendChild(xeCust);

     XmlElement XeOrderName=xdoc.CreateElment("OrderName");

     xeorderName.InnerText ="bj200000";

      Xeroot.AppendChild(xeOrderName);

     XmlElement xeItem=xdoc.CreateElement("Items");

      xeroot.AppendChild(xeItem);

      XmlElement order1=xdoc.CreateElement("OrderItem");

       order1.SetAttribute("Name","電腦");

        order1.SetAttribute("Count",30); 

Xpath簡介:

常用文法:

    /AAA  選擇根元素AAA

    /AAA/CCC 選擇AAA元素下的所有CCC子元素

    /AAA/BBB/CCC 選擇AAA元素下子元素BBB下所有CCC字元素

    //BBB 選擇所有BBB子元素

    //* 選擇所有元素

    /AAA/BBB[1] 選擇AAA下第一個BBB子元素

    //@id 選擇所有有id屬性的元素

    //BBB[@id] 選擇有id屬性的BBB元素

    //BBB[NOT(@*)] 選擇沒有屬性的BBB元素

    //BBB[@id=’b1’] 選擇id為b1的BBB元素

    //*[COUNT(BBB)=2] 選擇含有兩個BBB子元素的元素

    等等……..   用的時候可以查找

深拷貝與淺拷貝

深拷貝是把所有的資料都拷貝一份,包括引用都會拷貝,而淺拷貝隻是把值類型拷貝一份,而引用類型則沒有。

圖例:

      淺拷貝的實作(demo):

/// <summary>

        /// 實作對象的淺拷貝

        /// </summary>

        /// <returns></returns>

        public Person QianKaoBei()

        {

            //MemberwiseClone()方法從object類中繼承下來

            //作用就是把目前對象淺拷貝一份

            //淺拷貝目前對象

            return (Person)this.MemberwiseClone();

        }

      深拷貝(序列化實作):

static object DeepCopy(object src)

        {

            BinaryFormatter Formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));

            using (MemoryStream stream = new MemoryStream())

            {

                Formatter.Serialize(stream, src);

                stream.Position = 0;

                return Formatter.Deserialize(stream);

            }

        }

Attribute特性(attribute)

是被指定給某一聲明的一則附加的聲明性資訊

就是一個标簽,在使用目前類的地方,通過反射擷取該特性

Attribute就是類,Attribute類名一般都以Attribute結尾,使用的時候不用加Attribute這個結尾。使用Attribute的時候給的參數其實就是構造函數

反編譯DisplaynameAttribute,發現沒有特殊代碼。标簽本身是沒有含義,隻是起到标注的作用,具體怎麼解釋、使用這個辨別,是由使用者來決定:屬性視圖視窗、C#編譯器。相當于在放上畫一個“拆”,本身這個字沒有含義。

自定義特性(核心 反射):

      Attribute都從System. Attribute類繼承,類名一般以Attribute結尾

建立構造函數

标記類的用途—AttributeUsage标記(标記的标記):AttributeTargets:可以添加到哪些成員上。AllowMultiple:是否允許在一個成員上标記這個Attribute的多個執行個體,預設false。标注在Attribute類的類名上方。

Attribute隻是給類、成員做标記,本身沒有什麼意義,不會發生任何動作,就像小偷踩點在門上做标記(StealableAttribute)一樣,具體這個标記會起到什麼作用是由使用這個類、成員的代碼決定的。

Property.GetCustomerAttribute()

轉載于:https://www.cnblogs.com/reganLi/p/3401824.html