熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> ASP編程 >> 正文

.NET反射、委托技術與設計模式

2013-11-15 12:54:20  來源: ASP編程 

   反射技術與設計模式

  反射(Reflection)是NET中的重要機制通過放射可以在運行時獲得NET中每一個類型(包括類結構委托接口和枚舉等)的成員包括方法屬性事件以及構造函數等還可以獲得每個成員的名稱限定符和參數等有了反射即可對每一個類型了如指掌如果獲得了構造函數的信息即可直接創建對象即使這個對象的類型在編譯時還不知道

   NET可執行應用程序結構

  程序代碼在編譯後生成可執行的應用我們首先要了解這種可執行應用程序的結構

  應用程序結構分為應用程序域—程序集—模塊—類型—成員幾個層次公共語言運行庫加載器管理應用程序域這種管理包括將每個程序集加載到相應的應用程序域以及控制每個程序集中類型層次結構的內存布局

  程序集包含模塊而模塊包含類型類型又包含成員反射則提供了封裝程序集模塊和類型的對象我們可以使用反射動態地創建類型的實例將類型綁定到現有對象或從現有對象中獲取類型然後調用類型的方法或訪問其字段和屬性反射通常具有以下用途

  ()使用Assembly定義和加載程序集加載在程序集清單中列出模塊以及從此程序集中查找類型並創建該類型的實例

  ()使用Module了解包含模塊的程序集以及模塊中的類等還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法

  ()使用ConstructorInfo了解構造函數的名稱參數訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等使用Type的GetConstructors或GetConstructor方法來調用特定的構造函數

  ()使用MethodInfo了解方法的名稱返回類型參數訪問修飾符(如pulic 或private)和實現詳細信息(如abstract或virtual)等使用Type的GetMethods或GetMethod方法來調用特定的方法

  ()使用FiedInfo了解字段的名稱訪問修飾符(如public或private)和實現詳細信息(如static)等並獲取或設置字段值

  ()使用EventInfo了解事件的名稱事件處理程序數據類型自定義屬性聲明類型和反射類型等添加或移除事件處理程序

  ()使用PropertyInfo了解屬性的名稱數據類型聲明類型反射類型和只讀或可寫狀態等獲取或設置屬性值

  ()使用ParameterInfo了解參數的名稱數據類型是輸入參數還是輸出參數以及參數在方法簽名中的位置等

  SystemReflectionEmit命名空間的類提供了一種特殊形式的反射可以在運行時構造類型

  反射也可用於創建稱為類型浏覽器的應用程序使用戶能夠選擇類型然後查看有關選定類型的信息

  此外Jscript等語言編譯器使用反射來構造符號表SystemRuntimeSerialization命名空間中的類使用反射來訪問數據並確定要永久保存的字段SystemRuntimeRemoting命名空間中的類通過序列化來間接地使用反射

   反射技術示例

  下面是反射技術的示例我們可以在程序去得時動態實例化對象獲得對象的屬性並調用對象的方法

  

  Namespace ReflectionExample
{
class Class
{
[STAThread]
static void Main (string [ ] args)
{
SystemConsoleWriteLine(列出程序集中的所有類型);
Assembly a = AssemblyLoadFrom (ReflectionExampleexe);
Type[ ] mytypes = aGetTypes( );

Foreach (Type t in mytypes)
{
SystemConsoleWriteLine ( tName );
}
SystemConsoleReadLine ( );
SystemConsoleWriteLine (列出HellWord中的所有方法 );
Type ht = typeof(HelloWorld);
MethodInfo[] mif = htGetMethods();
foreach(MethodInfo mf in mif)
{
SystemConsoleWriteLine(mfName);
}
SystemConsoleReadLine();
SystemConsoleWriteLine(實例化HelloWorld並調用SayHello方法);
Object obj = ActivatorCreateInstance(ht);
string[] s = {zhenlei};
Object bojName = ActivatorCreateInstance(hts);
BindingFlags flags = (BindingFlagsNonPublic|BindingFlags
Public|BindingFlagsStatic|BindingFlagsInstance|BindingFlags
DeclaredOnly);
MethodInfo msayhello = htGetMethod(SayHello);
msayhelloInvoke(objnull);
msayhelloInvoke(objNamenull);
SystemConsoleReadLine();
}
}
}

  

  using System;
namespace ReflectionExample
{
public class HelloWorld
{
string myName = null;
public HelloWorld(string name)
{
myName = name;
}
public HelloWorld() : this(null)
{}
public string Name
{
get
{
return myName;
}
}
public void SayHello()
{
if(myName == null)
{
SystemConsoleWriteLine(Hello World);
}
else
{
SystemConsoleWriteLine(Hello + myName);
}
}
}
}

   在設計模式實現中使用反射技術

  采用反射技術可以簡化工廠的實現

  ()工廠方法通過反射可以將需要實現的子類名稱傳遞給工廠方法這樣無須在子類中實現類的實例化

  ()抽象工廠使用反射可以減少抽象工廠的子類

  采用反射技術可以簡化工廠代碼的復雜程度NET項目中采用反射技術的工廠已經基本代替了工廠方法

  采用反射技術可以極大地簡化對象的生成對以下設計模式的實現也有很大影響

  ()命令模式可以采用命令的類型名稱作為參數直接獲得命令的實例並且可以動態執行命令

  ()享元模式采用反射技術實例化享元可以簡化享元工廠

   委托技術與設計模式

  委托技術是NET引入的一種重要技術使用委托可以實現對象行為的動態綁定從而提高設計的靈活性

   NET中的委托技術

  NET運行庫支持稱為委托的引用類型其作用類似於C++中的函數指針與函數指針不同委托實例獨立於其封裝方法的類主要是那些方法與委托類型兼容另外函數指針只能引用靜態函數而委托可以引用靜態和實例方法委托主要用於NET Framework中的事件處理程序和回調函數

  所有委托都從SystemDelegate繼承而來並且有一個調用列表這是在調用委托時所執行方法的一個鏈接列表產生的委托可以用匹配的簽名引用任何方法沒有為具有返回類型並在調用列表中包含多個方法的委托定義返回值

  可以使用的委托Cimbine及Remove方法在其調用列表中添加和移除方法若要調用委托可使用Invoke方法或者使用BeginInvoke和EndInvoke方法異步調用委托委托類的實現由運行庫提供而不由用戶代碼提供

  委托適用於那種在某些語言中需要用函數指針來解決的情況但是與函數指針不同它是面向對象和類型安全的

  委托聲明定義一個類它是從SystemDelegate類派生的類委托實例封裝了一個調用列表其中列出了一個或多個方法每個方法稱為一個可調用實體對於實例方法可調用實體由一個實例和該實例的方法組成對於靜態方法可調用實體僅由一個方法組成如果用一組合適的參數來調用一個委托實例則該委托實例所封裝的每個可調用實體都會被調用並且使用上述同一組參數

  委托實例的一個有用的屬性是它既不知道也不關心其封裝方法所屬類的詳細信息對它來說最重要的是這些方法與該委托的類型兼容即只要方法的返回類型和參數表是相同的則方法與委托類型兼容方法的名稱不一定要與委托類相同

  定義和使用委托分為聲明實例化和調用個步驟委托用委托聲明語法聲明

  delegate void myDelegate( )

  聲明一個名為myDelegate的委托它不帶參數並且不返回任何結果

  

  class Test
{
static void F( )
{
SystemConsoleWriteLine (TestF);
}
static void Main ( )
{
myeDelegate d = new myDelegate (F);
d ( );
}
}

  創建一個myDelegate實例然後立即調用它這樣做並沒有太大的意義因為直接調用方法會更簡單當涉及其匿名特性時委托才能真正顯示出其效果

  

  void MultiCall (myDelegate d int count ) {
for (int I = ; I < count; I++) {
d( );
}
}

  顯示一個重復調用 myDelegate的MultiCall 方法這個方法不知道也不必知道myDelegate的目標方法的類型該方法具有的可訪問性或者是否為靜態對它來說最重要的是目標方法與myDelegate兼容

  示例

  下面的例子說明了委托的實現代碼如下

  

  using System;
namespace DelegateExample
{
public class TemplateMethod
{
public delegate float Comp(float afloat b);
public Comp myComp;
public TemplateMethod()
{}
public float DoComp(float[] f)
{
float nf = floatNaN;
foreach(float df in f)
{
if(floatIsNaN(nf))
nf = df;
else
nf = myComp(nfdf);
}
return nf;
}

}
}

   委托技術與GOF設計模式中委托的關系

  需要指出的是NET中的委托技術與GOF在《設計模式》中所提列的委托的意圖一致但在實現方法上有相當大的區別……NET中的委托更進一步地降低了對象間的耦合性將靜態的組合關系變為運行時的動態組合關系

  GOF在《設計模式》中定義的委托是委托是一種組合方法它使組合具有與繼承同樣的復用能力在委托方式下有兩個對象參與處理一個請求接受請求的對象將操作委托給它的代理者(delegate)它類似於子類將請求交給它的父類處理使用繼承時被繼承的操作總能引用接受請求的對象在C++中通過this成員變量在Smalltalk中則通過self委托方式為了得到同樣的效果接受請求的對象將自身傳給被委托者(代理人)使被委托的操作可以引用接受請求的對象

  如果采用NET的委托技術上述結構可以更加靈活Window不引用Rectangle即可實現Area的計算為此首先聲明一個計算面積的委托定義示例代碼如下

  public delegate float Darea()

  然而在Window類中聲明與這個代理一致的接口

  

  class Window
{
public Darea Area;
}
這裡不需要引用Rectangle類只是在執行時動態綁定即可
Rectangle rc = new Rectangle();
Window w = new Window();
wArea = new Darea(rcArea);

  這樣當調用w的Area時實際調用的是Reactangel的Area方法從實現意圖上看NET的委托更好地實現了GOF所闡述的意圖結構上也更為靈活但這兩種委托解決的不是一個層面的問題GOF的委托強調的是一種策略NET和委托技術則是具體實現

   委托技術與設計模式實現

  采用委托技術可以進一步實現用組合代替繼承的思路很多采用繼承實現的關系可以采用委托實現采用委托可以簡化下列設計模式的使用

  ()模板方法這種方法采用繼承實現具體方法采用委托可以動態實現方法的組合

  ()觀察者可以使用事件委托實現觀察者與主題之間的通信

  ()中介者使用委托可以去除工件與中介者之間的耦合關系


From:http://tw.wingwit.com/Article/program/ASP/201311/21848.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.