温故知新之:反射:加载程序集中的类,动态调用

lucialee 2020-02-12

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

//Net Reflector(收费)官方网址:http://www.red-gate.com/products/dotnet-development/reflector/  
//ILSpy/dnSpy 【免费】官方网址:http://ilspy.net/
//https://www.cnblogs.com/ldc218/p/8945892.html 推荐.Net、C# 逆向反编译四大工具利器 https://blog.csdn.net/kongwei521/article/details/54927689


//我们拿到一个别人写的程序集,可以用用各种反编译工具来分析其内部代码,也可以自己写代码来反射调用其内部代码:

namespace 得到程序集
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly[] Masms = AppDomain.CurrentDomain.GetAssemblies(); // 得到所有该程序加载的程序集
                                                                        //GetInfoFromAssembl(Masms);// 将产生大量的东西
                                                                        //从路径加载
                                                                        //string MfilePath = @"D:\201205Demos\反射案例、Attribute\测试程序集1\bin\Debug\测试程序集1.dll";


            string MfilePath = @"C:\Users\Administrator\source\repos\温故知新\测试程序集\bin\Debug\netstandard2.0\测试程序集.dll";
            Assembly Masm = Assembly.LoadFile(MfilePath);
            GetInfoFromAssembl(new Assembly[] { Masm });
            //CreateInstanceFromAssembly(Masm);

            Console.ReadKey();
        }
        /// <summary>
        /// 从程序集Assembly中获取信息
        /// </summary>
        /// <param name="Pasms"></param>
        static void GetInfoFromAssembl(Assembly[] Pasms)
        {
            foreach (Assembly Masm in Pasms)
            {
                Console.WriteLine("Location ======{0}", Masm.Location);
                Console.WriteLine("FullName ======{0}", Masm.FullName);
                GetInfoFromAssemblSub(Masm);
            }
        }
        /// <summary>
        /// 从程序集中获取类的信息,几乎都可以获得,这里只获得属性和方法
        /// </summary>
        /// <param name="Pasm"></param>
        private static void GetInfoFromAssemblSub(Assembly Pasm)
        {
            Type[] Mtypes = Pasm.GetTypes();//获得所加载程序集所有的类
            //Type[] Mtypes = Pasm.GetExportedTypes();//获得所加载程序集public类
            foreach (Type Mtype in Mtypes)
            {
                Console.WriteLine("Type ============================================================== {0}",Mtype);

                //PropertyInfo[] props = Mtype.GetProperties();//获得程序集所有的public属性
                PropertyInfo[] props = Mtype.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);//获得程序集所有的private属性
                //FieldInfo[] props = Mtype.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (PropertyInfo prop in props)
                {
                    Console.WriteLine("PropertyInfo:{0}", prop);
                }

                //MethodInfo[] methods = Mtype.GetMethods();//获得程序集所有的public方法

                MethodInfo[] methods = Mtype.GetMethods(BindingFlags.NonPublic|BindingFlags.Instance);//查找所有私有方法
                foreach (MethodInfo m in methods)
                {
                    Console.WriteLine(m);
                }

                //MethodInfo methodInfo = Mtype.GetMethod("Wife");
                MethodInfo methodInfo = Mtype.GetMethod("Wife",BindingFlags.NonPublic | BindingFlags.Instance);//得到特定的私有方法
                                                                                                               //Console.WriteLine(methodInfo);


                CreateInstanceFromAssembly(Mtype);

            }
        }
        /// <summary>
        /// 根据一个类型,创建一个实例
        /// </summary>
        /// <param name="Passembly"></param>
        private static void CreateInstanceFromAssembly(Type Ptype)
        {
            var Mobj = Activator.CreateInstance(Ptype);// 创建一个实例


            PropertyInfo propAge = Ptype.GetProperty("Age");//获得person类的age属性的描述(与实例无关)
            if (propAge != null)
            {
                propAge.SetValue(Mobj, 27, null);//第一个参数 要为哪个对象的age属性赋值
                PropertyInfo propName = Ptype.GetProperty("Name");
                propName.SetValue(Mobj, "tom", null);
                //调用方法
                MethodInfo methodsayhello = Ptype.GetMethod("SayHello");
                methodsayhello.Invoke(Mobj, null);

                MethodInfo methodWife = Ptype.GetMethod("Wife", BindingFlags.NonPublic | BindingFlags.Instance);//得到特定的私有方法
                methodWife.Invoke(Mobj, new object[] { "苍井空" }); 
            }

        }
    }
}


//namespace 测试程序集
//{
//    public class Person
//    {
//        public Person()
//        { Console.WriteLine("创建了一个人"); }
//        public string Name { get; set; }
//        public int Age { get; set; }
//        private int Gender { get; set; }
//        public void SayHello()
//        {
//            Console.WriteLine("My name is {0} and {1} years old", Name, Age);
//        }
//        private void Wife()
//        {
//            Console.WriteLine("Wife is private!");
//        }
//    }


//class TokyoHot
//{
//    public TokyoHot()
//    { Console.WriteLine("Tokyo Hot is private"); }
//}

//}


//获得Type对象的方法:
//通过类获得Type:Type t = typeof(Person)
//通过对象获得类的Type:Type t = p.GetType()
//调用Assembly的GetExportedTypes方法可以得到Assembly中定义的所有的public类型。
//调用Assembly的GetTypes()方法可以得到Assembly中定义的所有的类型。
//调用Assembly的GetType(name)方法可以得到Assembly中定义的全名为name的类型信息。

相关推荐