元数据与反射(二)

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 Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.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+"\n");
                    PrintTypeInfo(type);
                    Console.WriteLine("**************************" + "\n");
                }
                Console.WriteLine("================="+"\n");
            }
            Console.ReadKey();
        }

        static void PrintTypeInfo(Type t)
        {
            MemberInfo[] memberInfos = t.GetMembers();
            foreach (var memberInfo in memberInfos)
            {
                //根据memberInfo.MemberType来输出类型
                Console.WriteLine("名称:"+memberInfo.Name+"     类型"+memberInfo.MemberType+"\n");
            }
        }
    }

”类库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*");

 

posted @ 2017-04-09 20:51  杨老三帅  阅读(447)  评论(0编辑  收藏  举报