反射的使用

反射可以获得Dll里面的类,和对应类的属性,方法,特性,等一系列内容,而不用去添加引用

获得类中的各个内容

如何去添加一个Dll,并且获得对应的类,需要用到一个系统类,Assembly,然后使用Assembly.Load(),来导入Dll文件,然后通过Assembly实例的GetType,来获得类库中的具体类,这里面

的参数需要类的全称,然后根绝methodInfo,Property,field, CustomerAttribute等来获得方法,属性,字段,特性等内容

添加一个基础类Student

public class Student
    {

        public Student()
        {
            Console.WriteLine("无参构造函数");
        }

        public Student(string name, int age)
        {
            Name = name;
            Age = age;
        }


        public string PetName;

        [DisplayName("姓名")]
        public string Name { get; set; }
        public int Age { get; set; }

        
        public string Grade()
        {
            return "三年级";
        }

        public string Grade(string str)
        {
            return "三年级"+ str;
        }

        public string GetData(string str)
        {
            return str;
        }


        public static string StaticFun()
        {
            return "Static";
        }
        public static string StaticFun(string str)
        {
            return "Static"+str;
        }

        public string GetName<T>(T t)
        {
            return typeof(T).Name + t.ToString();
        }

        private string GetPrivateFun()
        {
            return "Private Fun";
        }
    }

然后在另一个项目中,加载当前Student生成的Dll,来实现反射获取属性

 Assembly assembly = Assembly.Load("ReflectClass");
                Type type = assembly.GetType("ReflectClass.Student");
                foreach (var item in type.GetFields())
                {
                    Console.WriteLine(item.Name);
                }

                foreach (var item in type.GetMethods())
                {
                    Console.WriteLine(item.Name);
                }
                foreach (var item in type.GetProperties())
                {
                    Console.WriteLine(item.Name);
                }
                foreach (var item in type.GetProperty("Name").GetCustomAttributes())
                {
                    Console.WriteLine(item.ToString());
                }
                Console.ReadLine();

简单工厂,配置切换代码逻辑

通过反射,咱们可以实现一个简单工厂,来进行配置试的数据库切换,通过面向接口编程,来定义IDBTest接口和DBSqlHelper和DBOracleHelper

 public interface IDBTest
    {
        string Connection { get; set; }

        string Add();

        string Delete();

        string Update();

        string Select();
    }
 public class SqlHelper : IDBTest
    {
        public string Connection { get; set; }

        public string Add()
        {
            return "Sql Add";
        }

        public string Delete()
        {
            return "Sql Delete";
        }

        public string Select()
        {
            return "Sql Select";
        }

        public string Update()
        {
            return "Sql Update";
        }
    }

 

 public class OracleHelper : IDBTest
    {
        public string Connection { get; set; }

        public string Add()
        {
            return "Oracle Add";
        }

        public string Delete()
        {
            return "Oracle Delete";
        }

        public string Select()
        {
            return "Oracle Select";
        }

        public string Update()
        {
            return "Oracle Update";
        }
    }

简单工厂

 public class SimplyFactory
    {
        private static string str = System.Configuration.ConfigurationManager.AppSettings["DBHelper"];
        private static string aStr = str.Split(',')[0];
        private static string tStr = str.Split(',')[1];
        public static T Instance<T>()
        {
            Assembly assembly = Assembly.Load(aStr);
            Type type = assembly.GetType(tStr);
            var helper = (T)Activator.CreateInstance(type);
            return helper;
        }
    }

配置文件

  <appSettings>
    <add key="DBHelper" value="DBHelper,DBHelper.OracleHelper"/>
  </appSettings>

主方法中,只需要通过以下代码就可以实现数据访问功能的实现,并且在需要求换数据请求逻辑的时候,更新配置文件即可,主函数不需要修改任何代码(面向借口编程)

Console.WriteLine("配置文件简单工厂");
                var helper = SimplyFactory.Instance<IDBTest>();
                Console.WriteLine(helper.Add());
                Console.WriteLine(helper.Delete());
                Console.ReadLine();

破坏单例

通过反射还可以调用类中的私有构造函数来破坏单例模式

public class SingleClass
    {
        private static SingleClass _singleClass = null;

        private SingleClass()
        {
            Console.WriteLine("singelClass 构造函数");
        } 

        static SingleClass()
        {
            _singleClass = new SingleClass();
        }

        public static SingleClass GetInstance()
        {
            return _singleClass;
        }
    }

主函数调用

 Assembly assembly = Assembly.Load("ReflectClass");
                Type type = assembly.GetType("ReflectClass.SingleClass");
                var data1 = Activator.CreateInstance(type, true);
                Console.ReadLine();

实例化泛型类

public class GenericClass<T,X,M>
    {
        public String Show(T t, X x, M m)
        {
            return typeof(T).Name + typeof(X).Name + typeof(M).Name;
        }
    }

主函数调用(`3 表示是三个泛型参数的类)

 Assembly assembly = Assembly.Load("ReflectClass");
                Type type = assembly.GetType("ReflectClass.GenericClass`3");
                Type type1= type.MakeGenericType(typeof(string), typeof(int), typeof(DateTime));
                var data = Activator.CreateInstance(type1);
                Console.WriteLine();

通过泛型来调用类的私有函数,重载函数,静态函数,泛型函数,(接着使用上面的Student类)

Assembly assembly = Assembly.Load("ReflectClass");
                Type type = assembly.GetType("ReflectClass.Student");
                var data = Activator.CreateInstance(type);
                var data1 = Activator.CreateInstance(type, new object[] { "张三", 12 });
                //var data2 = Activator.CreateInstance(type, new object[] { 11, "张三"});

                MethodInfo method = type.GetMethod("Grade",new Type[] { });
                Console.WriteLine(method.Invoke(data1, null));
                MethodInfo method1 = type.GetMethod("Grade", new Type[] {typeof(string)});

                Console.WriteLine(method1.Invoke(data1, new object[] { "一个参数" }));

                MethodInfo method2 = type.GetMethod("StaticFun", new Type[] { typeof(string)});
                Console.WriteLine(method2.Invoke(null, new object[] { "静态函数一个参数"}));

                MethodInfo method3 = type.GetMethod("GetName");
                MethodInfo method3_1 = method3.MakeGenericMethod(typeof(string));
                Console.WriteLine(method3_1.Invoke(data1, new object[] { "泛型" }));

                MethodInfo method4 = type.GetMethod("GetPrivateFun",BindingFlags.Instance|BindingFlags.NonPublic);
                Console.WriteLine(method4.Invoke(data1, null));

                PropertyInfo proper = type.GetProperty("Name");
                Console.WriteLine(proper.GetValue(data1));
                proper.SetValue( data1,"李四");
                Console.WriteLine(proper.GetValue(data1));

                Console.ReadLine();

反射的最大特点就是动态,代码不是写死的,而是可配置的,但是反射的使用会导致一定的性能损耗

posted @ 2019-02-24 15:35  我不是你的狗  阅读(170)  评论(0编辑  收藏  举报