Dart - Using and Retrieving Metadata Annotation

This tutorial shows you how to create metadata annotation in Dart and retrieve the metadata information at runtime.

In Dart, we can add metadata to class, field, method or constructor level by using annotation (@). It's usually used to provide additional information about the program.

Creating & Using Metadata Annotation

First, create a class that will be used as metadata annotation.

  class Todo {
    final String name;
    final String description;

    const Todo(this.name, this.description);
  }

Then, use that class as annotation by calling the constructor preceded by @. You can add annotation at class, field, method, or constructor.

  @Todo('Chibi', 'Rename class')
  class MyClass{
  
    @Todo('Tuwaise', 'Change fielld type')
    int value;
  
    @Todo('Anyone', 'Change format')
    void printValue() {
      print('value: $value');
    }

    @Todo('Anyone', 'Remove this')
    MyClass();
  }

Retrieving Annotation Metadata

To retrieve the annotation metadata, we can use reflection utils from Dart's mirrors package. First, get the InstanceMirror by using:

  InstanceMirror reflect(Object reflectee);

Then, get the type property of the InstanceMirror to get the ClassMirror. The metadata list for the Class can be obtained from ClassMirror's metadata property. To access each value, use metadata.reflectee.{fieldName}. But, in case there are multiple annotations with different field names, to avoid error, make sure that metadata.reflectee is an instance of the right annotation class - in this example, the Todo class..

For metadata at field, method, or constructor level, we need to get the list of the class's data members using classMirror.declarations.values. At each iteration, make sure the data member has non-empty metadata and the metadata's first.reflectee is an instance of the right annotation class.

  import 'dart:mirrors';

  void main() {
    MyClass myClass = new MyClass();
    InstanceMirror im = reflect(myClass);
    ClassMirror classMirror = im.type;
  
    classMirror.metadata.forEach((metadata) {
      if (metadata.reflectee is Todo) {
        print(metadata.reflectee.name);
        print(metadata.reflectee.description);
      }
    });
  
    for (var v in classMirror.declarations.values) {
      if (!v.metadata.isEmpty) {
        if (v.metadata.first.reflectee is Todo) {
          print(v.metadata.first.reflectee.name);
          print(v.metadata.first.reflectee.description);
        }
      }
    }
  }

That's how to use metadata annotation in Dart.