使用反射動態建立型別例項

2021-09-06 19:40:44 字數 3768 閱讀 6120

.net中除了建構函式外,還有多種方式可以建立型別的例項。下面總結了幾種常見的通過反射建立型別例項的方法。

假設我們需要建立有這樣乙個型別的例項:

public

class

employee

public

employee(string name)

public

employee ()

public

void

say(string greeting)

say:

", name, greeting));

}}

system.activator類中提供了三組靜態方法來建立型別的例項,每組方法均提供多個過載,適用不同的場景。個別過載方法返回objecthandle物件,需要unwrap後才能獲取物件例項。

createinstance

createinstancefrom

createcominstancefrom

以下例項**演示了如何使用上述方法建立物件例項:

//

使用無參建構函式

var employee = (employee)activator.createinstance(typeof

(employee));

employee = activator.createinstance();

employee.say(

"createinstance with default ctor");

//使用有參建構函式

employee=(employee)activator.createinstance(typeof(employee), new

object );

employee.say(

"createinstance with ctor with args");

string assembly ="

test, version=1.0.4562.31232, culture=neutral, publickeytoken=null";

string type="

test.tests.employee";

var employeehandle =activator.createinstance(

assembly,

type);

employee =(employee)employeehandle.unwrap();

employee.say(

"createinstance and unwrap.");

string assemblypath=@"

e:\studyproj\shartdev\test\test\bin\debug\test.exe";

employeehandle =activator.createinstancefrom(

assemblypath,

type);

employee =(employee)employeehandle.unwrap();

employee.say(

"createinstancefrom and unwrap.

");

createinstance

createinstanceandunwrap

createinstancefrom

createinstancefromandunwrap

使用type.invokermember可以呼叫型別的方法、屬性。自然也可以通過呼叫型別的建構函式來建立乙個型別的例項。

//

直接呼叫無參建構函式

object obj = typeof(employee).invokemember(null, bindingflags.createinstance, null, null, null

);employee employee =obj as

employee;

employee.say(

"invokemember default ctor");

//使用帶引數的建構函式

obj = typeof(employee).invokemember(null, bindingflags.createinstance, null, null, new

object );

employee = obj as

employee;

((employee)obj).say(

"invokemember ctor with argument

");

除了直接適用invokermember呼叫建構函式外,還可以先以反射的方式獲取建構函式對應的memberinfo,具體型別為constructorinfo,然後使用其invoke方法。

//

首先獲取建構函式,然後再invoke

constructorinfo ctor = typeof(employee).getconstructor(new type );

var emp = (employee)ctor.invoke(new

object);

emp.say(

"constructorinfo

");

本來一步可以完成的操作,分兩邊走完的確是麻煩了些,但好處在於獲取constructorinfo之後,後續多次呼叫invoke時,避免重複繫結,可以提高效率,適用於需要重複多次使用同乙個建構函式建立例項的場景。反射的繫結過程是按照字串比較的方式在程式集元資料中查詢匹配的成員,速度較慢。

array型別可以使用靜態方法array.createinstance方法建立。array類還提供了其他過載方法來建立多維陣列。

var array = array.createinstance(typeof(int),20

);console.writeline(array.gettype().name+"

" +array.length);

建立delegate型別需要使用delegate.createdelegate.

methodinfo methodinfo = typeof(createinstancetest).getmethod("

staticdosomething

",bindingflags.public|bindingflags.static);

delegate dele = delegate.createdelegate(typeof

(dosomethingdelegate),methodinfo);

dele.dynamicinvoke(

"just say hi

");

建立泛型型別的例項,首先要獲取對應的開放型別(open type)的引用,然後呼叫type型別的makegenerictype方法,傳入乙個包含泛型引數的陣列即可獲取乙個封閉型別(closed type).使用該封閉型別,呼叫activator接受type引數的某個方法既可以構造出具體的例項。

type open = typeof(dictionary<,>);

type closetype = open.makegenerictype(typeof(string),typeof(object

));object obj =activator.createinstance(closetype);

console.writeline(obj.gettype());

以上即是常用的幾種建立物件例項的方式,實際應用中可以根據具體場景做選擇。

出處:

使用反射動態建立Enum 不可能

朋友有個難題,要動態建立列舉,google了一下,基本都是不可能.自己寫了個 測試了一下,貌似確實不可能.關鍵就在於,在程式執行的時候可以發現已經創造出了乙個列舉,但是沒有辦法使用,即沒有辦法例項化.下面是我的測試 有興趣的放vs上跑跑,呵呵 using system using system.th...

C 反射 動態建立物件

上面部落格學習了使用反射檢視型別的資訊,以及使用反射獲取特性物件。下面使用反射來動態建立物件。首先準備乙個test類 public class testclass public testclass int a,int b public int show public static int show ...

動態建立Struct例項

pair struct.new token,word first word pair.new direction north second word pair.new verb go 定義乙個陣列,儲存這個新建的struct sentence first word,second word p sen...