反射的概念,用处
概念:反射是指对一个程序集中的元数据进行检查的过程。用处:
1) 访问程序集中类型的元数据。包括像完整的类型名,成员名的构造,及对一个构造进行修饰的特性。
2) 使用元数据,在运行时动态调用一个类型成员,而不是编译时绑定。
3) 枚举程序集中的所有类型,并搜索满足特定条件的类型。
使用 System.Type 访问元数据
基本功能:
- Type.Name : 类型名是什么
- Type.IsPublic : 类型是public 的吗
- Type.BaseType : 类型的基本类型是什么
- Type.GetInterfaces() : 类型支持任何接口吗
- Type.Assembly : 类型是在哪个程序集中定义的。
- Type.GetProperties() : 类型的属性
- Type.GetMethods() : 类型的方法
- Type.GetFields() : 类型的字段
程序实例: (getType() 和 typeof() 的例子)
http://msdn.microsoft.com/zh-cn/library/58918ffs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Reflect_Sample
{
class Program
{
public int m_Member1;
public string m_Member2;
static void Main(string[] args)
{
DateTime datatime = new DateTime();
Console.WriteLine("==================================================");
Console.WriteLine("Test GetType()");
Console.WriteLine("==================================================");
Type type = datatime.GetType();
Console.WriteLine("Type is :{0} \n", type.FullName);
foreach (System.Reflection.PropertyInfo property in type.GetProperties())
{
Console.WriteLine(property.Name);
}
Console.WriteLine("==================================================");
Console.WriteLine("Test typeof()");
Console.WriteLine("==================================================");
Type t = typeof(Program);
Console.WriteLine("Methods:");
System.Reflection.MethodInfo[] methodInfo = t.GetMethods();
foreach (System.Reflection.MethodInfo mInfo in methodInfo)
Console.WriteLine(" " + mInfo.ToString());
Console.WriteLine("Members:");
System.Reflection.MemberInfo[] memberInfo = t.GetMembers();
foreach (System.Reflection.MemberInfo mInfo in memberInfo)
Console.WriteLine(" " + mInfo.ToString());
Console.ReadKey();
}
}
}
成员调用
获取元数据并不是最终的目的,还可以更进一步动态调用它引用的成员。这里的例子主要是设置类中的属性值。其中包括静态的属性,普通的属性,和集合类型的
http://msdn.microsoft.com/zh-cn/library/vstudio/xb5dd1f1.aspx
程序实例: 使用反射来为对象的属性设置值
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
class Example
{
private static int _staticProperty = 41;
public static int StaticProperty
{
get
{
return _staticProperty;
}
set
{
_staticProperty = value;
}
}
private int _instanceProperty = 42;
public int InstanceProperty
{
get
{
return _instanceProperty;
}
set
{
_instanceProperty = value;
}
}
private Dictionary<int, string> _indexedInstanceProperty = new Dictionary<int, string>();
// By default, the indexer is named Item, and that name must be used
// to search for the property. In this example, the indexer is given
// a different name by using the IndexerNameAttribute attribute.
[IndexerNameAttribute("IndexedInstanceProperty")]
public string this[int key]
{
get
{
string returnValue = null;
if (_indexedInstanceProperty.TryGetValue(key, out returnValue))
{
return returnValue;
}
else
{
return null;
}
}
set
{
if (value == null)
{
throw new ApplicationException("IndexedInstanceProperty value can be the empty string, but it cannot be Nothing.");
}
else
{
if (_indexedInstanceProperty.ContainsKey(key))
{
_indexedInstanceProperty[key] = value;
}
else
{
_indexedInstanceProperty.Add(key, value);
}
}
}
}
public static void Main()
{
Console.WriteLine("Initial value of class-level property: {0}", Example.StaticProperty);
PropertyInfo piShared = typeof(Example).GetProperty("StaticProperty");
piShared.SetValue(null, 76, null);
Console.WriteLine("Final value of class-level property: {0}",Example.StaticProperty);
Example exam = new Example();
Console.WriteLine("\nInitial value of instance property: {0}", exam.InstanceProperty);
PropertyInfo piInstance = typeof(Example).GetProperty("InstanceProperty");
piInstance.SetValue(exam, 37, null);
Console.WriteLine("Final value of instance property: {0}", exam.InstanceProperty);
exam[17] = "String number 17";
exam[46] = "String number 46";
exam[9] = "String number 9";
Console.WriteLine("\nInitial value of indexed instance property(17): '{0}'", exam[17]);
// By default, the indexer is named Item, and that name must be used
// to search for the property. In this example, the indexer is given
// a different name by using the IndexerNameAttribute attribute.
PropertyInfo piIndexedInstance = typeof(Example).GetProperty("IndexedInstanceProperty");
piIndexedInstance.SetValue(exam,
"New value for string number 17",
new object[] { (int)17 });
Console.WriteLine("Final value of indexed instance property(17): '{0}'", exam[17]);
Console.ReadKey();
}
}
泛型类型的反射
在泛型类型上执行运行时反射,将判断出一个类或方法是否包含泛型类型,并确定它包含的任何类型的参数。1) 判断类型参数的类型
public class Stack<T>
{
public void Add(T i)
{
Type t = typeof(T); // 这里可以判断泛型参数的类型。
}
}
2) 判断类或方法是否支持泛型, 获取泛型类或方法类型参数
程序实例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Reflect_GenericType_Sample
{
class Program
{
static void Main(string[] args)
{
Type type;
type = typeof(Stack<>);
Console.WriteLine("Stack<> ContainsGenericParameters = {0}", type.ContainsGenericParameters);
Console.WriteLine("Stack<> IsGenericType = {0}", type.IsGenericType);
Console.WriteLine("");
type = typeof(Stack<int>);
Console.WriteLine("Stack<int> ContainsGenericParameters = {0}", type.ContainsGenericParameters);
Console.WriteLine("Stack<int> IsGenericType = {0}", type.IsGenericType);
Console.WriteLine("==============================================================");
Console.WriteLine("Test get generic type arguments");
Console.WriteLine("==============================================================");
Stack<string> s = new Stack<string>();
Type subt = s.GetType();
foreach(Type t in subt.GetGenericArguments())
{
Console.WriteLine("params: {0}", t.FullName);
}
Console.ReadKey();
}
}
}