Mike Mitterer
Mike Mitterer

Reputation: 7180

simpleName of annotation in DartLang with reflectable lib

Is this really the only way to get the simpleName of an annotation in Dart?

// 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";
}

Last line returns the SimpleName - seems a bit complicated?

    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

Upvotes: 1

Views: 339

Answers (1)

Erik Ernst
Erik Ernst

Reputation: 1054

At the point where you test expect(x,new isInstanceOf<MyAnnotation>()); you have essentially made the result of the computation trivial: It is statically known that the name of the class of an instance of MyAnnotation is "MyAnnotation".

However, if your actual usage context doesn't commit to the type of annotation statically then you would need a more dynamic approach. Obtaining a class mirror of the metadata object (as you do) is a general approach that will work, and you will also need something like the metaReflector to get support for looking up that class mirror. Btw, I don't see why you would need the metadataCapability on metaReflector, but I would expect it to require a typeCapability.

Note that the most recent versions of reflectable require a declarationsCapability in order to use instanceMembers and staticMembers (it was an anomaly to support them without that capability).

If you can make things a bit more static then you can choose some intermediate solutions: You could organize your metadata into a subtype hierarchy such that every instance of the kind of metadata that you will need to handle will have a nameOfClass method, or you could create a Map<Type, String> that would translate every type of metadata that you will handle into its name, or you could even (forgive me ;-) use toString() which will reveal the name of any object whose class doesn't override the toString() from Object.

Finally, I'd suggest that you consider using the Type value directly if you want to treat the metadata in a "somewhat dynamic" manner: You could look up x.runtimeType and make decisions based on comparison with MyAnnotation just as well as you could make decisions based on comparisons with the string "MyAnnotation", it's only if you want to do textual things like "any class whose name matches this regex will do here" that you gain anything from going via strings.

(It should be said that runtimeType is somewhat costly because it causes extra data to be preserved at runtime, esp. with dart2js, but that data is already needed when you use reflectable).

Upvotes: 3

Related Questions