c#中的反射

都說c#和java差不多即硼,會了java逃片,c#基本都會了。我對java還是很熟的只酥,對oc也比較熟褥实,但是c#感覺還是過一遍比較好。最近看到了c#的反射裂允,這里呢就對反射在各個語言中的體現(xiàn)橫向比較一下损离。

反射,讓程序員能夠根據(jù)一個字符串去:

  1. 實例化對象
  2. 調(diào)用想要的方法
  3. 遍歷類中或者對象中的屬性或者屬性值绝编。

意思就是能夠動態(tài)調(diào)用草冈。這樣會有非常非常大的好處,以及便捷性瓮增。反射這一套東西在開發(fā)業(yè)務(wù)中不是必須的怎棱,但是如果你想讓你的代碼有:

  1. 更好的組織性
  2. 更松的耦合性
  3. 更強的復(fù)用性

反射必須掌握。而且語言之間都是相通的绷跑。如果你是一個想偷懶的程序員拳恋,一定要掌握反射。

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就比較靈活一點

//第一種方式:這種方式有一定的不安全性砸捏,特別是當(dāng)類名從用戶那邊獲取的時候
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.如何通過一個字符串調(diào)用某個對象的某個方法

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);

//靜態(tài)函數(shù)公有
p.GetType().GetMethod("getaaa").Invoke(null,null)

//非靜態(tài)私有
var methodInfo2 = p.GetType().GetMethod("getaaa",BindingFlags.NonPublic | BindingFlags.Instance);
var  result =  methodInfo2.Invoke(p, null);

//靜態(tài)私有
 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中反射靜態(tài)方法和調(diào)用普通的公有私有方法無太大區(qū)別
//只是忽略了invoke中的對象參數(shù)
//getDeclaredMethod方法可以獲取當(dāng)前類的所有方法
//但是不包含繼承的方法谬运,如果想獲取繼承的方法,可以通過getSuperclass向上尋找垦藏。
//getMethod方法只會獲取public類型的

oc

//方式1:這種方式梆暖,最多支持2個參數(shù)
NSString *number = [obj performSelector:NSSelectorFromString(@"getNumber") withObject:nil withObject:nil];
//方式2
//支持多參
//導(dǎo)入#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文件中有沒有聲明都能被調(diào)用到

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");

//私有靜態(tài)
p.GetType().GetField("number",BindingFlags.NonPublic|BindingFlags.Static).SetValue(p,"123456");

Java

  Field field  =  Person.class.getDeclaredField("name");
 field.setAccessible(true);  //是否設(shè)置強制訪問私有
 field.set(p, "aaaa");          //設(shè)置字段值
 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(構(gòu)造器信息): 通過GetConstructors或者GetConstructor方法掂骏。

  2. 獲取某個類的EventInfo(類中的事件信息):通過GetEvents或者GetEvent方法轰驳。

  3. 獲取某個類的PropertyInfo(類中的屬性信息):通過GetProperties或者GetProperty方法。

  4. 如何加載程序集

    Assembly.Load("相對路徑");
    Assembly.LoadFrom("完整路徑");

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

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

Java中也有類似的反射方法弟灼,以獲取構(gòu)造器级解,等類中的一些定義屬性。
OC 是動態(tài)語言就反射來說效率會高于靜態(tài)語言java和c#田绑。
Javascript總的來說是最靈活的勤哗。

反射還有很多,這里就不一一贅述掩驱,總的來說使用率比較高的就是我介紹的這幾個芒划。當(dāng)然實際肯定還有各種各樣的需求,慢慢查api吧欧穴,總結(jié)是總結(jié)不完的民逼,這里只是把常用的列出來。

PS:寫代碼這么久了苔可,還沒有像樣的博客缴挖,之前建了三次,忘了三次都被阿里云最后回收了焚辅。這次換社區(qū)試試映屋,希望能堅持下去。會把以前的筆記同蜻,經(jīng)驗棚点,還有工作中的一些問題,總結(jié)一下湾蔓,慢慢的放到博客上瘫析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贬循,更是在濱河造成了極大的恐慌咸包,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杖虾,死亡現(xiàn)場離奇詭異烂瘫,居然都是意外死亡,警方通過查閱死者的電腦和手機奇适,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門坟比,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嚷往,你說我怎么就攤上這事葛账。” “怎么了皮仁?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵籍琳,是天一觀的道長。 經(jīng)常有香客問我魂贬,道長巩割,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任付燥,我火速辦了婚禮宣谈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘键科。我一直安慰自己闻丑,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般旱物。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侥祭,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音茄厘,去河邊找鬼矮冬。 笑死,一個胖子當(dāng)著我的面吹牛次哈,可吹牛的內(nèi)容都是我干的胎署。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼窑滞,長吁一口氣:“原來是場噩夢啊……” “哼琼牧!你這毒婦竟也來了恢筝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤巨坊,失蹤者是張志新(化名)和其女友劉穎撬槽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抱究,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡恢氯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鼓寺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡勋磕,死狀恐怖妈候,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挂滓,我是刑警寧澤苦银,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站赶站,受9級特大地震影響幔虏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贝椿,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一想括、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧烙博,春花似錦瑟蜈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乔宿,卻和暖如春位迂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背详瑞。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工掂林, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛤虐。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓党饮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親驳庭。 傳聞我的和親對象是個殘疾皇子刑顺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容