反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。
反射的功能很强大,任何复杂抽象的分层架构或者复杂的设计模式均是建立在这些基础之上的,比如我们要进行模块化、组件化开发,要严格的消除模块之间的耦合,要进行动态接口调用。开发这样强大而灵活的系统,必须要用反射才行,我们只要把它用在合适的位置,不仅能使代码变的清晰简洁,更能让它发挥出惊人的力量。
反射的用途
类型 | 作用 |
---|---|
Assembly | 定义和加载程序集,加载程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。 |
Module | 了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 |
ConstructorInfo | 了解构造器的名称、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数。 |
MethodInfo | 了解方法的名称、返回类型、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。 |
FieldInfo | 了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。 |
EventInfo | 了解事件的名称、事件处理程序数据类型、自定义特性、声明类型和反射类型等,并添加或移除事件处理程序。 |
PropertyInfo | 了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,并获取或设置属性值。 |
ParameterInfo | 了解参数的名称、数据类型、参数是输入参数还是输出参数等,以及参数在方法签名中的位置等。 |
(一)自定义一个类库,自定义一个类
namespace 环环环环环 { public class User { //字段 public string Field; //属性 public string Name { get; set; } //构造函数 public User() { this.Name = "无参构造"; } public User(string name) { this.Name = name; } //public函数 public void PublicShow() { Console.WriteLine(string.Format("反射调用一个public方法")); } //private函数 private void PrivateShow() { Console.WriteLine(string.Format("反射调用一个Private方法")); } //static函数 public static string StaticMethod() { return "反射调用了一个Static方法"; } //带参带返回值函数 public string GetString(string name) { return string.Format("大家好,我的名字是:{0}!", name); } //事件 public event EventHandler eventHandler; //事件处理函数 public void DoEvent() { if(eventHandler != null) eventHandler(null, EventArgs.Empty); } } }
2、新建一个project,把上面编译好的库 环环环环环.dll 复制到Debug目录下
加载程序集
//获取程序集 Assembly assembly = Assembly.Load("环环环环环"); Assembly assembly2 = Assembly.LoadFrom("环环环环环.dll"); //从程序集中获取指定对象类型; Type type = assembly.GetType("环环环环环.User"); //使用Activator创建实例(无参数构造函数) var user1 = Activator.CreateInstance(type); //使用Activator创建实例(带参数构造函数) var user2 = Activator.CreateInstance(type, "薄暮"); //使用Assembly创建实例(无参数构造函数) var user3 = assembly.CreateInstance("环环环环环.User"); //反射无参构造函数 ConstructorInfo constructor1 = type.GetConstructor(new Type[] {}); var user4 = constructor1.Invoke(new object[] { }); //反射有参构造函数 ConstructorInfo constructor2 = type.GetConstructor(new Type[] { typeof(string) }); var user5 = constructor2.Invoke(new object[] { "薄暮" }); //调用public函数(无参数) type.InvokeMember("PublicShow", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, user1, null); //调用public函数(带参数) string returnValue = type.InvokeMember("GetString", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, user1, new object[] { "薄暮" }) as string; // 调用静态方法 string returnValue2 = type.InvokeMember("StaticMethod", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] {}) as string; // 调用私有方法 . type.InvokeMember("PrivateShow", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, user1, new object[] {}); //反射属性 var Name = type.InvokeMember("Name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, user1, new object[] {}) as string; //设置属性(设置Name属性为"新属性") type.InvokeMember("Name", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, user1, new object[] {"新属性"}); //反射字段 string Field = type.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null, user1, new object[] {}) as string; //设置字段(设置Field字段为"新字段") type.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null, user1, new object[] { "新字段" });
(二)System.Type类
System.Type类对于反射有很重要的作用。它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。
获取给定类型的Type值有三种常用方式:
- 使用C# typeof运算符
Type t=typeof(string); - 使用对象的GetType()方法
string s=”guo”;Type t=s.GetType(); - 调用Type类的静态方法GetType()
Type t=Type.GetType(“System.String”);
获取程序集信息
namespace ReflectionTest
{
class ReflectionHelper
{
public void GetAssemblyInfo()
{
Assembly assembly = Assembly.GetExecutingAssembly();
Console.WriteLine("程序集全名:{0}", assembly.FullName);
Console.WriteLine("程序集的版本:{0}", assembly.GetName().Version);
Console.WriteLine("程序集初始位置:{0}", assembly.CodeBase);
Console.WriteLine("程序集位置:{0}", assembly.Location);
Console.WriteLine("程序集入口:{0}", assembly.EntryPoint);
Type[] types = assembly.GetTypes();
Console.WriteLine("程序集中包含的类型:");
foreach (Type item in types)
{
Console.WriteLine("类:" + item.Name);
}
}
}
}
获取类型信息
namespace ReflectionTest
{
class ReflectionHelper
{
public void GetTypeInfo()
{
Type type = typeof(Person);
Console.WriteLine("类型名:{0}", type.Name);
Console.WriteLine("类全名:{0}", type.FullName);
Console.WriteLine("命名空间:{0}", type.Namespace);
Console.WriteLine("程序集名:{0}", type.Assembly);
Console.WriteLine("模块名:{0}", type.Module);
Console.WriteLine("基类名:{0}", type.BaseType);
Console.WriteLine("是否类:{0}", type.IsClass);
Console.WriteLine("类的公共成员:");
MemberInfo[] members = type.GetMembers();
foreach (MemberInfo memberInfo in members)
{
Console.WriteLine("{0}:{1}", memberInfo.MemberType, memberInfo);
}
}
}
}
反射调用方法
namespace ReflectionTest
{
class ReflectionHelper
{
public void InvokeMethod()
{
#region 方法一
Assembly assembly1 = Assembly.Load("ReflectionTest");
Type type1 = assembly1.GetType("ReflectionTest.Person");
object obj1 = System.Activator.CreateInstance(type1);
MethodInfo method1 = type1.GetMethod("Show");
method1.Invoke(obj1, null);
#endregion
#region 方法二
object obj2 = Assembly.Load("ReflectionTest").CreateInstance("ReflectionTest.Person");
Type type2 = obj2.GetType();
MethodInfo method = type2.GetMethod("Show");
method.Invoke(obj2, null);
#endregion
}
}
}
反射实现工厂模式
namespace ReflectionTest
{
class Program
{
static void Main(string[] args)
{
//方法一
AbsFruit absFruit = FruitFactory.CreateInstance<AbsFruit>("ReflectionTest", "Strawberry");
absFruit.Show();
//方法二
//string fullTypeName = typeof (Strawberry).FullName;
string fullTypeName = typeof (Strawberry).AssemblyQualifiedName;
AbsFruit absFruit2 = FruitFactory.CreateInstance<AbsFruit>(fullTypeName);
absFruit2.Show();
}
}
}
namespace ReflectionTest
{
public class FruitFactory
{
public static T CreateInstance<T>(string nameSpace,string className)
{
string fullClassName = nameSpace + "." + className;
return (T)Assembly.Load(nameSpace).CreateInstance(fullClassName);
}
public static T CreateInstance<T>(string fullTypeName)
{
return (T)Activator.CreateInstance(Type.GetType(fullTypeName));
}
}
}
public abstract class AbsFruit
{
protected string Name { get; set; }
public abstract void Show();
}
class Strawberry:AbsFruit
{
public Strawberry()
{
Name = "草莓";
}
public override void Show()
{
Console.WriteLine("水果类型:" + Name);
}
}