2015-12-21 74 views
1

這是真正獲得Dart中註釋的simpleName的唯一方法嗎?DartLang中註釋的簡單名稱,帶有可反射的元素

// Annotate with this class to enable reflection. 
class Reflector extends Reflectable { 
    const Reflector() 
     : super(
      invokingCapability,metadataCapability 
     ); 
} 

const reflector = const Reflector(); 

// Reflector for annotation 
class MetaReflector extends Reflectable { 
    const MetaReflector() 
     : super(metadataCapability); 
} 
const metareflector = const MetaReflector(); 

@metareflector 
class MyAnnotation { 
    final String name; 
    const MyAnnotation(this.name); 
} 

@reflector // This annotation enables reflection on A. 
class A { 
    final int a; 
    A(this.a); 

    int valueFunction() => a; 
    int get value => a; 

    @MyAnnotation("James Bond") 
    String nameFunction() => "Mike"; 
} 

最後一行返回SimpleName - 看起來有點複雜?

test('> Annotation',() { 
     final A a = new A(10); 
     final InstanceMirror im = reflector.reflect(a); 
     final ClassMirror cm = im.type; 

     Map<String, MethodMirror> instanceMembers = cm.instanceMembers; 
     expect(instanceMembers.keys.contains("valueFunction"),isTrue); 
     expect(instanceMembers.keys.contains("value"),isTrue); 
     expect(instanceMembers.keys.contains("nameFunction"),isTrue); 

     final MethodMirror mm = instanceMembers["nameFunction"]; 
     expect(mm.isRegularMethod,isTrue); 

     expect(mm.metadata.length,1); 

     final x = mm.metadata.first; 
     expect(x,new isInstanceOf<MyAnnotation>()); 
     expect((x as MyAnnotation).name,"James Bond"); 

     final InstanceMirror imAnnotation = metareflector.reflect(x); 
     final ClassMirror cmAnnotation = imAnnotation.type; 

     expect(cmAnnotation.simpleName,"MyAnnotation"); 
    }); // end of 'Annotation' test 

回答

3

,在您測試expect(x,new isInstanceOf<MyAnnotation>());你已經基本上作出的計算微不足道的結果了這一點:它是靜態已知的類MyAnnotation實例的名稱爲"MyAnnotation"。然而,如果你的實際使用上下文沒有靜態地提交註解類型,那麼你需要一個更動態的方法。獲取元數據對象的類鏡像(與您一樣)是一種可行的常規方法,您還需要像metaReflector之類的內容來獲得對查找該類鏡像的支持。順便說一句,我不明白你爲什麼需要metadataCapabilitymetaReflector,但我希望它需要typeCapability

注意的是,最近的可反射的版本才能使用instanceMembersstaticMembers(這是支持他們沒有這種能力的異常)需要declarationsCapability

如果您可以使事情更靜一些,那麼您可以選擇一些中間解決方案:您可以將您的元數據組織到子類型層次結構中,以便您需要處理的每種元數據類型都有一個nameOfClass方法,或者你可以創建一個Map<Type, String>來翻譯你將要處理的每種類型的元數據到它的名字中,或者你甚至可以(原諒我;-)使用toString()這將揭示任何對象的名字,這些對象的類不會覆蓋toString()Object

最後,我建議直接,如果你想治療的元數據在「有點動態」的方式,你可以考慮使用Type值:你可以查找x.runtimeType,並根據與MyAnnotation比較判決一樣好你可以根據與字符串"MyAnnotation"進行比較來做出決定,只有當你想做「像這個正則表達式的名字匹配的任何類將在這裏做的」這樣的文本事情時,你才能從字符串中獲得任何東西。 (應該說runtimeType的價格有點高,因爲它會在運行時導致額外的數據被保留,特別是使用dart2js,但是當您使用反射時,這些數據已經是需要的)。

+0

謝謝埃裏克,非常有幫助! expect(x,new isInstanceOf ());只是爲了測試理論與現實的對比。 我最後的做法更具活力。我正在使用lib來驗證對象成員。像這樣:@EMail(message:const L10N(「{{value}}不是有效的電子郵件地址」)) String username; 而且如果違規失敗,我需要type/simpleName來返回有意義的錯誤消息。 再次感謝! –