使用反射动态创建类型实例
.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());
以上即是常用的几种创建对象实例的方式,实际应用中可以根据具体场景做选择。
出处:http://www.cnblogs.com/dytes/archive/2012/06/29/2569488.html
=======================================================================================
C# 通过反射来动态创建泛型类型
第一部份:知道 泛型类型,但泛型参数需要动态的情况
先看一个简单的例子。
class Class1<T>
{
public void Test(T t)
{
Console.WriteLine(t);
}
}
要利用反射动态创建该类型实例,并调用 Test 方法,我们可以使用如下方法
Type type = typeof(Class1<int>);
object o = Activator.CreateInstance(type);
type.InvokeMember("Test", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, new object[] { 123 });
若泛型参数是未定的,可采用如下方法:
static void InvokeTest(Type t, params object[] args)
{
Type type = typeof(Class1<>);
type = type.MakeGenericType(t);
object o = Activator.CreateInstance(type);
type.InvokeMember("Test", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, args);
}
另外一种情况就是泛型方法,
class Class1
{
public void Test<T>(T t)
{
Console.WriteLine(t);
}
}
方法类似,只不过这回使用的是 MethodInfo.MakeGenericMethod()
static void InvokeTest(Type t, params object[] args)
{
Type type = typeof(Class1);
object o = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("Test", BindingFlags.Instance | BindingFlags.Public);
method = method.MakeGenericMethod(t);
method.Invoke(o, args);
}
当然还有实例化一个泛型
例如有GenericType<M,N>
Type genericType = typeof(GenericType<>);
Type[] templateTypeSet = new[] { typeof(string), typeof(int) };
Type implementType = genericType.MakeGenericType( templateTypeSet );
这样 implementType类型就是赋予了string,int的泛型类了
第二种部份:泛型类型及参数均需要动态指定的情况
Type entityType = typeof(T);
Assembly assy = Assembly.GetExecutingAssembly();
//注意:以下字符串中的`1表示泛型参数占位符个数,一个泛型参数则表示为:`1,多个泛型参数则表示为:`N;
string genericTypeAssyName = string.Format("{0}.{1}Repository`1", assy.GetName().Name,entityType.Name);
出处:http://www.zuowenjun.cn/post/2015/07/22/174.html
=======================================================================================
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/4100048.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2014-11-15 18:51 jack_Meng 阅读(6759) 评论(0) 编辑 收藏 举报