(1)定義:程序員
索引器是一種特殊的類成員,它可以讓對象以相似數組的形式來存取,使程序看起來更爲直觀,更容易編寫。編程
定義形式以下:數組
[修飾符] 數據類型 this[索引類型 index]app
{ide
get{//得到屬性的代碼}函數
set{//設置屬性的代碼}測試
}this
其中,修飾符包括:public,protected,private,internal,new,virtual,sealed,override, abstract,extern.spa
(2)實現Demo:插件
【單參數索引器】
static void Main(string[] args)
{
//通常索引器(參數爲int類型)
Console.WriteLine("--------------int類型做爲下標對索引器進行存儲------------------");
var worker = new IndexerWork();
worker[0] = "liupeng";
worker[1] = "zhangyonghe";
Console.WriteLine(string.Format("一號員工的名字爲:{0}", worker[0]));
Console.WriteLine(string.Format("二號員工的名字爲:{0}", worker[1]));
Console.WriteLine("--------------string類型做爲下標對索引器進行存儲---------------");
//索引器(參數爲string類型)
var ht = new IndexerWork();
ht["AA"] = "liupeng";
ht["BB"] = "zhangyonghe";
Console.WriteLine(string.Format("一號員工的名字爲:{0}", ht["AA"]));
Console.WriteLine(string.Format("二號員工的名字爲:{0}", ht["BB"]));
Console.ReadKey();
}
public class IndexerWork
{
public string[] Worker = new string[10];
private readonly Hashtable Ht = new Hashtable();
public string this[int index]
{
get { return Worker[index]; }
set { Worker[index] = value; }
}
public string this[string index]
{
get { return Ht[index].ToString(); }
set { Ht.Add(index, value); }
}
}
運行結果爲:
【多參數索引器】
//多參數索引器
var moreIndexer = new IndexerWork();
moreIndexer[1, "AA"] = "I am work in BaiDu!";
moreIndexer[2, "BB"] = "I am work in LeTv";
Console.WriteLine(string.Format("一員工的公司爲:{0}", moreIndexer[1, "AA"]));
Console.WriteLine(string.Format("二員工的公司爲:{0}", moreIndexer[2, "BB"]));
public class IndexerWork {
private readonly List_stuList = new List();
public string this[int index, string name]
{
get
{
var list = _stuList.Find(x => x.StuNo == index && x.StuName == name);
return list.ClassName;
}
set
{
_stuList.Add(new StudentInfo()
{
StuNo = index,
StuName = name,
ClassName = value
}
);
}
}
}
運行結果爲:
(1)定義:
delegate 是表示對具備特定參數列表和返回類型的方法的引用的類型。在實例化委託時,你能夠將其實例與任何具備兼容簽名和返回類型的方法相關聯—— MSDN
就我我的理解而言,委託能夠看作一個函數的指針,能夠把一個函數做爲一個參數帶入到另外一個函數中;也就是函數能夠把本身委託給聲明的委託對象,進行一系列的操做。
定義形式以下:
public delegate int PerformCalculation(int x, int y);
【1】簡單委託
定義DeletegateDemo,並實現兩個方法GetStatus和GetSimpleSign,分別接受一個int類型的參數:
public class DeletegateDemo
{
public void GetStatus(int num)
{
if (num > 0)
{
Console.WriteLine("大於0");
}
else if (num < 0)
{
Console.WriteLine("小於0");
}
}
public static void GetSimpleSign(int num)
{
if (num > 0)
{
Console.WriteLine("+");
}
else if (num < 0)
{
Console.WriteLine("—");
}
}
}
可利用委託,咱們能夠講兩個方法做爲參數傳遞給委託對象,進行操做。首先在Main函數外面聲明委託對象
public delegate void GetMySignDeletegate(int num);
而後在Main函數裏面咱們能夠這樣實現:
static void Main(string[] args)
{
var signObj = new DeletegateDemo();
var mySignDelegateOne = new GetMySignDeletegate(signObj.GetStatus);
var mySignDelegateTwo = new GetMySignDeletegate(DeletegateDemo.GetSimpleSign);
mySignDelegateOne(5);
mySignDelegateTwo(-3);
Console.ReadKey();
}
運行結果爲:
【2】多播委託
委託能夠包含多個方法,這種委託稱爲多播委託。若是調用多播委託,就能夠按順序連續調用多個方法。爲此,委託的簽名必須返回void,不然就只能獲得委託調用的最後一個方法的結果。
多播委託可使用運算符「+」和「+=」添加方法,也可使用「-」和「-=」從委託中刪除方法調用。
所以咱們能夠在Main函數中經過「+」和「—「來進行委託的注入和去除。
static void Main(string[] args)
{
var signObj = new DeletegateDemo();
var mySignDelegateOne = new GetMySignDeletegate(signObj.GetStatus);
var mySignDelegateTwo = new GetMySignDeletegate(DeletegateDemo.GetSimpleSign);
GetMySignDeletegate myDeletegate = null;
myDeletegate += mySignDelegateOne;
myDeletegate += mySignDelegateTwo;
myDeletegate(4);
}
運行結果爲:
三.反射
(1)定義
Reflection,中文翻譯爲反射。這是.Net中獲取運行時類型信息的方式,.Net的應用程序由幾個部分:‘程序集(Assembly)’、‘模塊(Module)’、‘類型(class)’組成,而反射提供一種編程的方式,讓程序員能夠在程序運行期得到這幾個組成部分的相關信息,例如:
Assembly類能夠得到正在運行的裝配件信息,也能夠動態的加載裝配件,以及在裝配件中查找類型信息,並建立該類型的實例。
Type類能夠得到對象的類型信息,此信息包含對象的全部要素:方法、構造器、屬性等等,經過Type類能夠獲得這些要素的信息,而且調用之。
MethodInfo包含方法的信息,經過這個類能夠獲得方法的名稱、參數、返回值等,而且能夠調用之。
諸如此類,還有FieldInfo、EventInfo等等,這些類都包含在System.Reflection命名空間下。
(2)實現Demo
【1】Type類於獲取類型信息
定義class,咱們能夠在Main函數中獲取定義類型的相關信息:
static void Main(string[] args)
{
var reflctionObject=new MyReflection();
var type = reflctionObject.GetType();
Console.WriteLine("類型名:" + type.Name);
Console.WriteLine("類全名:" + type.FullName);
Console.WriteLine("命名空間名:" + type.Namespace);
Console.WriteLine("程序集名:" + type.Assembly);
Console.WriteLine("模塊名:" + type.Module);
Console.WriteLine("基類名:" + type.BaseType);
Console.WriteLine("是否類:" + type.IsClass);
Console.WriteLine("類的公共成員:");
var memberInfos = type.GetMembers();//獲得全部公共成員
foreach (var item in memberInfos)
{
Console.WriteLine("{0}:{1}", item.MemberType, item);
}
Console.ReadKey();
}
//定義class
public class MyReflection
{
public string m = null;
public string Name { get; set; }
public void ShowMessage()
{
Console.WriteLine("My name is liupeng!");
}
}
運行結果:
【2】 獲取程序集元數據
static void Main(string[] args)
{
//獲取當前執行代碼的程序集
Assembly assem = Assembly.GetExecutingAssembly();
Console.WriteLine("程序集全名:"+assem.FullName);
Console.WriteLine("程序集的版本:"+assem.GetName().Version);
Console.WriteLine("程序集初始位置:"+assem.CodeBase);
Console.WriteLine("程序集位置:"+assem.Location);
Console.WriteLine("程序集入口:"+assem.EntryPoint);
Type[] types = assem.GetTypes();
Console.WriteLine("程序集下包含的類型:");
foreach (var item in types)
{
Console.WriteLine("類:"+item.Name);
}
}
運行結果:
【3】 動態加載類型
早綁定是在編譯時綁定對象類型,而晚綁定是在運行時才綁定對象的類型。利用反射能夠實現晚綁定,即動態加載類型,並調用他們的方法
static void Main(string[] args)
{
//動態建立類型
//獲取當前執行代碼的程序集
Assembly assem = Assembly.GetExecutingAssembly();
Console.WriteLine("Assembly Full Name:");
Console.WriteLine(assem.FullName);
// The AssemblyName type can be used to parse the full name.
AssemblyName assemName = assem.GetName();
Console.WriteLine("\\\\nName: {0}", assemName.Name);
Console.WriteLine("Version: {0}.{1}",
assemName.Version.Major, assemName.Version.Minor);
Console.WriteLine("\\\\nAssembly CodeBase:");
Console.WriteLine(assem.CodeBase);
// 從程序集中建立一個Example實例而且用object類型的引用o指向它,同時調用一個輸入參數的構造函數
Object o = assem.CreateInstance("Reflection.Example", false,
BindingFlags.ExactBinding,
null, new Object[] { 2 }, null, null);
//構造Example類的一個晚綁定的方法SampleMethod
MethodInfo m = assem.GetType("Reflection.Example").GetMethod("SampleMethod");
//調用剛纔實例化好的Example對象o中的SampleMethod方法,傳入的參數爲42
Object ret = m.Invoke(o, new Object[] { 42 });
Console.WriteLine("SampleMethod returned {0}.", ret);
Console.WriteLine("\\\\nAssembly entry point:");
Console.WriteLine(assem.EntryPoint);
Console.ReadKey();
}
public class Example
{
private int factor;
public Example(int f)
{
factor = f;
}
public int SampleMethod(int x)
{
Console.WriteLine("\\\\nExample.SampleMethod({0}) executes.", x);
return x * factor;
}
}
運行結果爲:
(1)使用反射經過讀取配置文件來動態的建立相關類的對象
//主函數
public static void Main()
{
#region 同程序集下
System.Type type = System.Type.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
ILog log = (ILog)Activator.CreateInstance(type);
log.Write(new Exception("異常測試"));
#endregion
#region 不一樣程序集
string assemblyPath = Path.Combine(Environment.CurrentDirectory, "LogClassLibrary.dll");
Assembly a = Assembly.LoadFrom(assemblyPath);
Type type = a.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
LogClassLibrary.ILog log = (LogClassLibrary.ILog)type.InvokeMember(null,BindingFlags.CreateInstance,null,null,null);
log.Write(new Exception("異常測試"));
#endregion
}
//app.config
//方法實現
public class TextFileLog : ILog
{
public bool Write(string message)
{
string fileDir = ConfigurationManager.AppSettings["LogTarget"].ToString();
using (StreamWriter w = File.AppendText(fileDir))
{
// w.Write(" Log Entry : ");
w.WriteLine("發生時間{0}", DateTime.Now.ToLocalTime().ToString());
w.WriteLine("日誌內容爲:{0}", message);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
w.Close();
}
return true;
}
public bool Write(Exception ex)
{
Write(ex.Message);
return true;
}
}
運行之後在C盤目錄下,能夠看到日誌記錄:
(2)插件編程技術
插件是指遵循必定的接口規範、能夠動態加載和運行的程序模塊。從上面的例子能夠看出,經過反射能夠很是方便的動態加載程序集。所以,利用反射的動態加載代碼能力,能夠很容易的實現插件。
插件編程的要點是使用接口來定義插件的功能特徵。插件的宿主程序經過接口來確認、裝載和執行插件的功能,實現插件功能的全部類都必須實現定義插件的接口。
【1】宿主加載插件
public class Host : IHost {
private Listplugins = new List();
#region IHost 成員
public ListPlugins
{
get { return plugins; }
}
public int LoadPlugins(string path)
{
string[] assemblyFiles = Directory.GetFiles(path, "*.dll");
foreach (var file in assemblyFiles)
{
Assembly assembly = Assembly.LoadFrom(file);
foreach (var type in assembly.GetExportedTypes())
{
if (type.IsClass && typeof(ILog).IsAssignableFrom(type))
{
ILog plugin = Activator.CreateInstance(type) as ILog;
plugins.Add(plugin);
}
}
}
return plugins.Count;
}
public ILog GetLog(string name)
{
foreach (var item in plugins)
{
if (item.GetType().ToString()==name)
{
return item;
}
}
return null;
}
#endregion
【2】接口定義 public interface IHost { ListPlugins { get; }
int LoadPlugins(string path);
ILog GetLog(string name);
}
【3】主函數調用
static void Main(string[] args)
{
Host.Host host = new Host.Host();
host.LoadPlugins(".");
InterfaceLayer.ILog log = host.GetLog(ConfigurationManager.AppSettings["LogType"].ToString());
log.Write(new Exception("異常測試"));
}