2015-12-21 38 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来返回有意义的错误消息。 再次感谢! –