美文网首页
c#中的反射

c#中的反射

作者: 修行猿 | 来源:发表于2016-06-23 12:42 被阅读247次

    都说c#和java差不多,会了java,c#基本都会了。我对java还是很熟的,对oc也比较熟,但是c#感觉还是过一遍比较好。最近看到了c#的反射,这里呢就对反射在各个语言中的体现横向比较一下。

    反射,让程序员能够根据一个字符串去:

    1. 实例化对象
    2. 调用想要的方法
    3. 遍历类中或者对象中的属性或者属性值。

    意思就是能够动态调用。这样会有非常非常大的好处,以及便捷性。反射这一套东西在开发业务中不是必须的,但是如果你想让你的代码有:

    1. 更好的组织性
    2. 更松的耦合性
    3. 更强的复用性

    反射必须掌握。而且语言之间都是相通的。如果你是一个想偷懒的程序员,一定要掌握反射。

    1.如何从一个字符串实例化一个类

    c#

    Type type = Type.GetType("Person",true);
    Person p =  (Person)System.Activator.CreateInstance(type);
    

    java

     Object o = Class.forName("com.company.Main").newInstance();
    

    oc

    Class class = NSClassFromString(@"YXTestObject");
    YXTestObject *obj= [[class alloc] init];
    或者
    Class class = objc_getClass("YXTestObject");
     YXTestObject *obj= [[class alloc] init];
    

    js

    //js就比较灵活一点
    
    //第一种方式:这种方式有一定的不安全性,特别是当类名从用户那边获取的时候
    var myStr = "Product"
    var p = eval("new " + myStr + "()");
    
    //第二种:将类定义在一个域中
    var mynamespace = {};
    mynamespace.Person = function Person() {..}
    var p = new mynamespace["Person"]();
    
    //如果直接定义在全局域可以这样:
    var p = new window["Person"]();
    

    2.如何通过一个字符串调用某个对象的某个方法

    c#

    Person p = new Person();
    
    //有参公有
    var methodInfo =   p.GetType().GetMethod("set_Name");
    methodInfo.Invoke(p, new string[] {"aaa"});
    
    //无参公有
    var methodInfo2 = p.GetType().GetMethod("get_Name");
    var  name =  methodInfo2.Invoke(p, null);
    
    //静态函数公有
    p.GetType().GetMethod("getaaa").Invoke(null,null)
    
    //非静态私有
    var methodInfo2 = p.GetType().GetMethod("getaaa",BindingFlags.NonPublic | BindingFlags.Instance);
    var  result =  methodInfo2.Invoke(p, null);
    
    //静态私有
     var methodInfo2 = p.GetType().GetMethod("getaaa",BindingFlags.NonPublic | BindingFlags.Static);
     var  name =  methodInfo2.Invoke(p, null);
    

    java

    //公有
    Person p =(Person) Class.forName("com.company.Person").newInstance();
    String number =   (String)Person.class.getMethod("getNumber", null).invoke(p,null);
    
    //私有
    Person p =(Person) Class.forName("com.company.Person").newInstance();
    Method method =   Person.class.getDeclaredMethod("getNumber", null);
    method.setAccessible(true);
    String number=(String)method .invoke(p,null);
    
    //Java中反射静态方法和调用普通的公有私有方法无太大区别
    //只是忽略了invoke中的对象参数
    //getDeclaredMethod方法可以获取当前类的所有方法
    //但是不包含继承的方法,如果想获取继承的方法,可以通过getSuperclass向上寻找。
    //getMethod方法只会获取public类型的
    

    oc

    //方式1:这种方式,最多支持2个参数
    NSString *number = [obj performSelector:NSSelectorFromString(@"getNumber") withObject:nil withObject:nil];
    //方式2
    //支持多参
    //导入#import <objc/message.h>
    //Build Setting--> Apple LLVM 6.0 - Preprocessing--> Enable Strict Checking of objc_msgSend Calls  改为 NO
    //否则会报Too many arguments to function call ,expected 0,have3
    NSString *number2 = objc_msgSend(obj,NSSelectorFromString(@"getNumber"),nil);
    
    //类方法
    NSString *number2 = objc_msgSend(class,NSSelectorFromString(@"getNumber"),nil);
    
    //NSSelectorFromString(@"getNumber")等价于sel_registerName("getNumber")
    
    //上面的几种方式不管在h文件中有没有声明都能被调用到
    

    js

    //js就非常简单了
    var p = new Person();
    var number = p["getNumber"]();
    

    3.通过属性名称字符串获取某个对象的字段值

    c#

    //公有
    p.GetType().GetField("number").SetValue(p,"123456");
    
    //私有
    p.GetType().GetField("number",BindingFlags.NonPublic|BindingFlags.Instance).SetValue(p,"123456");
    
    //私有静态
    p.GetType().GetField("number",BindingFlags.NonPublic|BindingFlags.Static).SetValue(p,"123456");
    

    Java

      Field field  =  Person.class.getDeclaredField("name");
     field.setAccessible(true);  //是否设置强制访问私有
     field.set(p, "aaaa");          //设置字段值
     String name = (String)field.get(p);  //获取字段值
    

    oc

    //可以通过kvc的方式,成员变量不管被声明在m文件还是h文件
    //不管是私有还是公有都能通过这种方式被访问到
     YXTestObject *obj= [[class alloc] init];
    [obj setValue:@"男" forKey:@"sex"];
    NSLog(@"%@",[obj valueForKey:@"sex"]);
    

    js

    js依然是最简单的
    var p =  new Person();
    p["number"]="123456";
    var number= p["number"];
    

    4.遍历某个对象的字段以及字段值

    c#

    public class Test {        
    public static void reflect(Object o){  
      
        PropertyInfo[] propertys = o.GetType().GetProperties();  
        foreach (PropertyInfo pinfo in propertys)  
        {  
            Console.WriteLine(pinfo.Name+","+pinfo.GetValue(o,null));  
        }  
    }  
    static void Main(string[] args){  
        Person p = new Person();  
        reflect(p);  
    }  
    

    }

    java

    public class Test {        
    public static void reflect(Object o) throws Exception{  
        Class cls = o.getClass();  
        Field[] fields = cls.getDeclaredFields();  
        for(int i=0; i<fields.length; i++){  
            Field f = fields[i];  
            f.setAccessible(true);  
            System.out.println("属性名:" + f.getName() + " 属性值:" + f.get(o));  
        }   
    }  
    public static void main(String[] args) throws Exception{  
        Person p = new Person();  
        reflect(p);  
    }  
    

    }

    oc

    +(NSString*)reflectWithObj:(id)obj
    {
        NSString *name = nil;
        NSString *value =nil;
        uint32_t ivarCount;
    
        Ivar *ivars = class_copyIvarList([obj class], &ivarCount);
        
        if(ivars)
        {
            for(uint32_t i=0; i<ivarCount; i++)
            {
                Ivar ivar = ivars[i];
                
                name = [NSString stringWithUTF8String:ivar_getName(ivar)];
                value=[obj valueForKey:name];
                NSLog(@"name=%@,value=%@",name,value==nil?@"nil":value);
            }
            
            free(ivars);
        }
    
        return name;
    }   
    

    Js

    function allPrpos ( obj ) {   
        var props = "" ;   
        for ( var p in obj ){   
            if ( typeof ( obj [ p ]) == " function " ){   
            obj [p]() ;   
            } else {   
                props += p + " = " + obj [ p ] + " \t " ;   
            }   
        }   
        console.log( props ) ;   
    }
    

    c#中类似的还有

    1. 获取某个类的ConstructorInfo(构造器信息): 通过GetConstructors或者GetConstructor方法。

    2. 获取某个类的EventInfo(类中的事件信息):通过GetEvents或者GetEvent方法。

    3. 获取某个类的PropertyInfo(类中的属性信息):通过GetProperties或者GetProperty方法。

    4. 如何加载程序集

      Assembly.Load("相对路径");
      Assembly.LoadFrom("完整路径");

    5. 如何取得程序集中所有的Type

      Type[] types = Assembly.Load("aaa").GetTypes();

    Java中也有类似的反射方法,以获取构造器,等类中的一些定义属性。
    OC 是动态语言就反射来说效率会高于静态语言java和c#。
    Javascript总的来说是最灵活的。

    反射还有很多,这里就不一一赘述,总的来说使用率比较高的就是我介绍的这几个。当然实际肯定还有各种各样的需求,慢慢查api吧,总结是总结不完的,这里只是把常用的列出来。

    PS:写代码这么久了,还没有像样的博客,之前建了三次,忘了三次都被阿里云最后回收了。这次换社区试试,希望能坚持下去。会把以前的笔记,经验,还有工作中的一些问题,总结一下,慢慢的放到博客上。

    相关文章

      网友评论

          本文标题:c#中的反射

          本文链接:https://www.haomeiwen.com/subject/lpnndttx.html