好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

反射动态创建类型示例

反射动态创建类型示例

.NET中除了构造函数外,还有多种方式可以创建类型的实例。下面总结了几种常见的通过反射创建类型实例的方法。

假设我们需要创建有这样一个类型的实例:

 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后才能获取对象实例。

CreateInstance

CreateInstanceFrom

CreateComInstanceFrom

以下实例代码演示了如何使用上述方法创建对象实例:

 //   使用无参构造函数 
 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。

CreateInstance

CreateInstanceAndUnwrap

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

以上即是常用的几种创建对象实例的方式,实际应用中可以根据具体场景做选择。

 

 

分类:  C#

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于反射动态创建类型示例的详细内容...

  阅读:41次