1.反射程序集
获取Assmbly对象有以下方法:
(1)Assmbly.Load("程序集文件名称")
Assembly assembly = Assembly.Load("类库Demo");
(2)Assmbly.LoadFrom("程序集文件名")
Assembly assembly = Assembly.LoadFrom("类库Demo.dll");
上述两个方法的区别就在于Load只需要提供文件名不加后缀的信息即可。
(3)反射当前的程序集 Assmbly.GetExecutingAssembly()
Assembly assembly = Assembly.GetExecutingAssembly();
值得注意的是,对于引用同一解决方案的其他项目生成的程序集,Load和LoadFrom只需要提供程序集名就可以了,但是对于非本解决方案下得程序集,则需要提供程序集的完整路径了。
Assembly assembly2 = Assembly.LoadFrom(@"C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5System.dll");
否则会报以下错误:
2.程序集中的成员信息与MemberInfo类型
代码如下图
public class Program { static void Main(string[] args) { Assembly assembly = Assembly.Load("类库Demo"); Module[] moudles = assembly.GetModules();//一个程序集中有多个模块(可以理解为多个独立的文件) foreach (var moudle in moudles) { Console.Write("Moudle名称:"+moudle.Name); Type[] types = moudle.GetTypes();//一个模块又有多个类型(可以理解为一个类文件中又有多个类、接口、枚举、委托等) foreach (var type in types) { Console.WriteLine("Type名称:"+type.Name+" "); PrintTypeInfo(type); Console.WriteLine("**************************" + " "); } Console.WriteLine("================="+" "); } Console.ReadKey(); } static void PrintTypeInfo(Type t) { MemberInfo[] memberInfos = t.GetMembers(); foreach (var memberInfo in memberInfos) { //根据memberInfo.MemberType来输出类型 Console.WriteLine("名称:"+memberInfo.Name+" 类型"+memberInfo.MemberType+" "); } } }
”类库Demo”中包含了以下代码:包含了类、接口、委托、事件、属性、字段、方法等信息
public class ClassLabiry { public string OtherInfo { get; set; } public void PrintOtherInfo() { Console.WriteLine(OtherInfo); } } public abstract class FatherClass { } public struct structDemo { } public delegate void MyDelegate(string name); public enum Day { monday=1, sunday=2 } public interface IDemoInterfaceOne { void SayHello(); } public interface IDemoInterfaceTwo { } public sealed class DemoClass : FatherClass, IDemoInterfaceOne, IDemoInterfaceTwo { private string name; public string city; public readonly string title; public const string text = "Const Field"; public event MyDelegate myEvent; public string Name { private get { return name; } set { name = value; } } public DemoClass() { title = "Readonly Field"; } public class NestedClass { } public void SayHello() { Console.WriteLine("Good Morning" + name); } }
输出的结果为:
Moudle名称:类库Demo.dllType名称:ClassLabiry 名称:get_OtherInfo 类型Method 名称:set_OtherInfo 类型Method 名称:PrintOtherInfo 类型Method 名称:ToString 类型Method 名称:Equals 类型Method 名称:GetHashCode 类型Method 名称:GetType 类型Method 名称:.ctor 类型Constructor 名称:OtherInfo 类型Property ************************** Type名称:FatherClass 名称:ToString 类型Method 名称:Equals 类型Method 名称:GetHashCode 类型Method 名称:GetType 类型Method ************************** Type名称:structDemo 名称:Equals 类型Method 名称:GetHashCode 类型Method 名称:ToString 类型Method 名称:GetType 类型Method ************************** Type名称:MyDelegate 名称:Invoke 类型Method 名称:BeginInvoke 类型Method 名称:EndInvoke 类型Method 名称:GetObjectData 类型Method 名称:Equals 类型Method 名称:GetInvocationList 类型Method 名称:GetHashCode 类型Method 名称:DynamicInvoke 类型Method 名称:get_Method 类型Method 名称:get_Target 类型Method 名称:Clone 类型Method 名称:ToString 类型Method 名称:GetType 类型Method 名称:.ctor 类型Constructor 名称:Method 类型Property 名称:Target 类型Property ************************** Type名称:Day 名称:Equals 类型Method 名称:GetHashCode 类型Method 名称:ToString 类型Method 名称:ToString 类型Method 名称:CompareTo 类型Method 名称:ToString 类型Method 名称:ToString 类型Method 名称:HasFlag 类型Method 名称:GetTypeCode 类型Method 名称:GetType 类型Method 名称:value__ 类型Field 名称:monday 类型Field 名称:sunday 类型Field ************************** Type名称:IDemoInterfaceOne 名称:SayHello 类型Method ************************** Type名称:IDemoInterfaceTwo ************************** Type名称:DemoClass 名称:add_myEvent 类型Method 名称:remove_myEvent 类型Method 名称:set_Name 类型Method 名称:SayHello 类型Method 名称:ToString 类型Method 名称:Equals 类型Method 名称:GetHashCode 类型Method 名称:GetType 类型Method 名称:.ctor 类型Constructor 名称:Name 类型Property 名称:myEvent 类型Event 名称:city 类型Field 名称:title 类型Field 名称:text 类型Field 名称:NestedClass 类型NestedType ************************** Type名称:NestedClass 名称:ToString 类型Method 名称:Equals 类型Method 名称:GetHashCode 类型Method 名称:GetType 类型Method 名称:.ctor 类型Constructor ************************** =================
3.BindFlag对检索对象可访问性的过滤
上面的DemoClass 中私有字段name并没有被打印出来,其实是因为在获取Member成员时有BindFlag的过滤。BindFlag是一个枚举类型,给检索加上了条件。
用法如下:
MemberInfo[] memberInfo = t.GetMembers( BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly )
对于私有字段访问,上面的代码可以改为:
MemberInfo[] memberInfos = t.GetMembers( BindingFlags.NonPublic | BindingFlags.Instance );
本以为NonPublic一个就可以了,不知道为啥实验了几次这两个出现才打印出来,得找找资料再看看了。
另外还可以配合MemberTypes枚举进行类型的过滤,如下
MemberInfo[] memberInfos = t.FindMembers( MemberTypes.Method, // 说明查找的成员类型为 Method BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.FilterName, "*");
Type.FilterName表示一个委托,该委托用于筛选 System.Reflection.MemberInfo 对象数组中表示的成员列表。,最后一个参数“*”,说明返回所有方法(如果使用"Print*",则会返回所有以Print开头的方法)。
MemberInfo[] memberInfos = t.FindMembers( MemberTypes.Method, // 说明查找的成员类型为 Method BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.FilterName, "Print*");