使用反射动态建立类型实例

.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

相关文章
相关标签/搜索