使用反射動態建立類型實例

.NET中除了構造函數外,還有多種方式能夠建立類型的實例。下面總結了幾種常見的經過反射建立類型實例的方法。html

假設咱們須要建立有這樣一個類型的實例:數組

public class Employee
{
    public String Name { get; set; }
    public Employee(String name)
    {
        Name = name;
    }

    public Employee ()
    {
    }

    public void Say(String greeting)
    {
        Console.WriteLine(String.Format("Employee {0} say: {1} ", Name, greeting));
    }
}

 

System.Activator

System.Activator類中提供了三組靜態方法來建立類型的實例,每組方法均提供多個重載,適用不一樣的場景。個別重載方法返回ObjectHandle對象,須要unwrap後才能獲取對象實例。函數

CreateInstancepost

CreateInstanceFromspa

CreateComInstanceFromcode

如下實例代碼演示瞭如何使用上述方法建立對象實例:orm

// 使用無參構造函數
var employee = (Employee)Activator.CreateInstance(typeof(Employee));
employee = Activator.CreateInstance<Employee>();
employee.Say("CreateInstance with default ctor");

// 使用有參構造函數
employee=(Employee)Activator.CreateInstance(typeof(Employee), new object[] { "David" });
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.");

 

System.AppDomain

與Activator相似,AppDomain提供了4組實例方法建立類型的實例。除了建立對象外,還指定了對象所歸屬的AppDomain。htm

CreateInstance對象

CreateInstanceAndUnwrapblog

CreateInstanceFrom

CreateInstanceFromAndUnwrap

 

System.Type

使用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[] { "david" });
employee = obj as Employee;
((Employee)obj).Say("InvokeMember ctor with argument");

 

 

System.Reflection.ConstructorInfo

除了直接適用InvokerMember調用構造函數外,還能夠先以反射的方式獲取構造函數對應的MemberInfo,具體類型爲ConstructorInfo,而後使用其Invoke方法。

// 首先獲取構造函數,而後再Invoke
ConstructorInfo ctor = typeof(Employee).GetConstructor(new Type[] { typeof(string) });
var emp = (Employee)ctor.Invoke(new object[]{"david"});
emp.Say("ConstructorInfo");

原本一步能夠完成的操做,分兩邊走完的確是麻煩了些,但好處在於獲取ConstructorInfo以後,後續屢次調用Invoke時,避免重複綁定,能夠提升效率,適用於須要重複屢次使用同一個構造函數建立實例的場景。反射的綁定過程是按照字符串比較的方式在程序集元數據中查找匹配的成員,速度較慢。

 

數組,委託和泛型類型的建立

Array

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");

Generic

建立泛型類型的實例,首先要獲取對應的開放類型(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());

 

以上便是經常使用的幾種建立對象實例的方式,實際應用中能夠根據具體場景作選擇。

 

出處:http://www.cnblogs.com/dytes/archive/2012/06/29/2569488.html

相關文章
相關標籤/搜索