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