反射

 文本较差,具体请看代码,如有错误,欢迎指出

1.反射生成类步骤:
加载DLL(【Assembly】.Load,LoadFile,LoadFrom),LoadFrom实质上也是调用Load,但是可以指定全路径
获取格式
实例化
object DB=Activator.CreateInstance(Tp);【属于Object类,无法调用方法】
[类型] ODB=(类型)DB;【需要强制转换后才可以使用】



2.调用方法
  4.1 构造函数:

object DB=Activator.CreateInstance(Tp);
  4.1.1 调用私有构造函数:
  object DB=Activator.CreateInstance(Tp,true);

4.1.2 生成泛型构造函数:若反射的类为DBHelper<T,W,X>,则
Type Tp=As.GetType("ConsoleApp1.SayHello`2");【包含2个占位符,需要写入】
Type NewTp=Tp.MakeGenericType(typeof(string), typeof(int));【重新生成一个新的类型,需要将类型赋给泛型然后生成该新的类型】
object DB=Activator.CreateInstance(NewTp);【使用新类型创建对象】

4.1.3 调用有参数的构造函数:构造函数为DBHelper(int x,string y){};DBHelper(string X){};【两个构造函数】
Assembly As=Assembly.Load("Ruanmou.DB.Sqlserver");
Type Tp=As.GetType("Ruanmou.DB.Sqlserver.DBHelper");
object DB1=Activator.CreateInstance(Tp,new object{223,"Abc"});【传递参数调用对应的构造函数,会根据传递的参数的类型调用对应的构造函数】
object DB2=Activator.CreateInstance(Tp,new object{"Abc"});【传递的参数必须跟已经有的构造函数的位置和类型一致,否则会报错】、

4.2 方法:(DB1 是已经实例化的类,且未强制转换的Object类型 Tp为获取的类型)
4.2.1 无参数实例化方法 :Show1(){};
MethodInfo method=Tp.GetMethod("Show1");
method.Invoke(DB1,null);

4.2.2 有参数实例化方法 :Show2(int x){};
MethodInfo method=Tp.GetMethod("Show2");
method.Invoke(DB1,new object{123});

4.2.3 有参数静态方法 :static Show3(int x){};
MethodInfo method=Tp.GetMethod("Show3");
method.Invoke(null,new object{123});【可以传递实例,但是不会调用】

4.2.3 多个重载方法 : Show4(){};Show4(int x){};Show4(string y){};Show4(int x,string y){};Show4(string y,int x){};
MethodInfo method1=Tp.GetMethod("Show3",new Type{});【调用无参重载】
MethodInfo method2=Tp.GetMethod("Show3",new Type{typeof(int)});【调用带一个Int重载】
MethodInfo method3=Tp.GetMethod("Show3",new Type{typeof(string)});
MethodInfo method4=Tp.GetMethod("Show3",new Type{typeof(int),typeof(string)});
MethodInfo method5=Tp.GetMethod("Show3",new Type{typeof(string),typeof(int)});

method1.Invoke(DB1);【无参数不必传递参数】
method2.Invoke(DB1,new object{123});【有参数的必须传递对应参数】
method3.Invoke(DB1,new object{"abc"});【】
method4.Invoke(DB1,new object{123,"abc"});【参数的类型,位置都必须一致】
method5.Invoke(DB1,new object{"abc",123});【】

4.2.4 调用私有方法: Private Show5 (){};
MethodInfo method=Tp.GetMethod("Show5",BingDingFlags.NonPublic|BingDingFlags.Instance);【获取私有属性必须两个都写上】
method.Invoke(DB1);

4.2.5 调用泛型方法: Show6<T>(T a){};
MethodInfo method=Tp.GetMethod("Show6");
Newmethod = method.MakeGenericMethod(typeof(string));【设置泛型为string】
Newmethod.Invoke(DB1,new object{"abc"});

4.3 属性和字段
4.3.1 获取和设置属性(DB1 是已经实例化的类,且未强制转换的Object类型 Tp为获取的类型)
foreach(var item in Tp.GetProperties())
{
item.GetValue();
if(item.Name=="Name")
{
item.SetValue(DB1,"abc");
}
if(item.Name=="ID")
{
item.SetValue(DB1,100001);
}
}
var Property=Tp.GetProperty("属性名"[,BingDingFlags.NonPublic|BingDingFlags.Instance]) 【获取指定的属性名,加后面内容可以获取私有属性】
var Filed=Tp.GetFiled("字段名"[,BingDingFlags.NonPublic|BingDingFlags.Instance]) 【获取指定的字段名,加后面内容可以获取私有属性】

类:

  public class Hello
    {
        public string Name{ get;  set; } 
        string Sex { get;  set; } 

        public void PublicSayHello()
        {
            Console.WriteLine(string.Format(@"无参公有方法:{0} {1}! Hello! ", Sex, Name));
        }

        public void PublicSayHello(int tip)
        {
            Console.WriteLine(string.Format(@"带参公有方法 tip{2}:{0} {1}! Hello! ", Sex, Name,tip));
        }

        private void PrivateSayHello()
        {
            Console.WriteLine(string.Format(@"无参私有方法 :{0} {1}! Hello! ", Sex, Name));
        }

        public void PublicGenericSayHello<G>(G tip)
        {
            Console.WriteLine(string.Format(@"带参泛型公有方法 tip{2}:{0} {1}! Hello! ", Sex, Name, tip));
        }


        private Hello(string name,string sex="PrivateSex") { Name = name;Sex = sex; }

        public Hello() { Sex = "PublicSex"; }//因为定义了一个有参构造函数,所以需要

        public Hello(string name) { Name = name; Sex = "PublicSex"; }//因为定义了一个有参构造函数,所以需要
    }

    public class SayHello<T,W>
    {
  
        T LastName { get; set; }
        T FirstName { get; set; }
        W Age { get; set; }

        public void PublicSayHello()
        {
            Console.WriteLine(string.Format(@"无参公有方法:{0} {1},you are {2}!! ", FirstName, LastName, Age));
        }

     

        public SayHello(T firstName,T lastName, W age) { FirstName = firstName; LastName = lastName; Age = age; }
    }
View Code

 方法:注意将DLL的路径,完全限定的类型替换

Assembly ass = Assembly.Load("ConsoleApp1");//获取bin下的dll
            Assembly Loadass = Assembly.LoadFrom(@"E:\laiji\WebApplication1\ConsoleApp1\bin\Debug\netcoreapp2.0\ConsoleApp1.dll");//获取路径下的dll
            Assembly Thisass = Assembly.GetExecutingAssembly();//获取本程序集的dll
            {
                Type T1 = ass.GetType("ConsoleApp1.Hello");
                Type T2 = Loadass.GetType("ConsoleApp1.Hello");
                Type T3 = Thisass.GetType("ConsoleApp1.Hello");
                Type T4 = typeof(Hello);//直接获取类型


                object[] Parms = new object[2];//参数列表,必须和构造函数的参数对应
                Parms[0] = "ObjectName";
                Parms[1] = "ObjectSex";

                var data1 = Activator.CreateInstance(T1) as Hello;//未进行转换无法调用下面的方法和赋值,调用无参公有构造函数
                data1.Name = "TestMan";
                data1.PublicSayHello();

                var data2 = Activator.CreateInstance(T1,new object[] { "PublicParmsName"}) as Hello;//未进行转换无法调用下面的方法和赋值,调用无参公有构造函数
                data2.PublicSayHello();

                //注意,使用的构造方法不同
                var PrivateData = ass.CreateInstance(T3.FullName, true, BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic, null, Parms, null, null) as Hello;//调用私有有参构造函数
                PrivateData.PublicSayHello();

                //调用方法
                {
                    Console.WriteLine("********************调用方法****************");
                    MethodInfo PublicMethod1 = T1.GetMethod("PublicSayHello", new Type[] { });//调用公有方法,如果方法没有重载可以省略new Type[] { }
                    PublicMethod1.Invoke(PrivateData, null);//null为参数列表,必须一一对应

                    MethodInfo PublicMethod2 = T1.GetMethod("PublicSayHello", new Type[] { typeof(int) });//调用公有方法,如果有重载,要在后面加上参数类型列表,必须一一对应
                    PublicMethod2.Invoke(PrivateData, new object[] { 1 });//null为参数列表,必须一一对应

                    MethodInfo PrivateMethod1 = T1.GetMethod("PrivateSayHello", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);//调用私有方法
                    PrivateMethod1.Invoke(PrivateData, null);

                    MethodInfo PublicMethod3 = T1.GetMethod("PublicGenericSayHello");//调用泛型方法
                    MethodInfo Newmethod = PublicMethod3.MakeGenericMethod(typeof(int));
                    Newmethod.Invoke(PrivateData, new object[] { 1 });
                }

                //修改属性,字段
                {
                    Console.WriteLine("********************修改属性,字段****************");
                    //1.遍历获取,仅能获取公有属性
                    foreach (var item in T1.GetProperties())
                    {
                        item.SetValue(PrivateData, "SetValueForeach");//设置属性的值,为了方便,将所有属性的值都设为SetValueForeach
                    }
                    PrivateData.PublicSayHello();

                    //2.获取指定属性
                    PropertyInfo Pt1 = T1.GetProperty("Name");//公有属性
                    Pt1.SetValue(PrivateData, "SetValueUsePropertyName");
                    PrivateData.PublicSayHello();

                    PropertyInfo Pt2 = T1.GetProperty("Sex",BindingFlags.Instance|BindingFlags.NonPublic);//私有属性
                    Pt2.SetValue(PrivateData, "SetValueUsePropertyNameBySex");
                    PrivateData.PublicSayHello();

                    //字段同属性,仅将Property换成Field
                }
            }
            {
                Console.WriteLine("********************调用泛型构造函数****************");
                //泛型构造函数
                Type Tp = ass.GetType("ConsoleApp1.SayHello`2");//后面要带占位符`2
                Type NewType = Tp.MakeGenericType(typeof(string), typeof(int));//需要新建一个泛型类型
                var Data = Activator.CreateInstance(NewType, new object[] {"FFN","LLN",18 }) as SayHello<string,int>;//使用泛型类型创建实例
                Data.PublicSayHello();
            }
View Code

 

 


























posted @ 2018-04-23 12:37  刘Te  阅读(668)  评论(3编辑  收藏  举报