Files
cherrypick/cherrypick_annotations
Sergey Penkovsky f85036d20f chore(release): publish packages
- cherrypick@3.0.0-dev.9
 - cherrypick_annotations@1.1.2-dev.0
 - cherrypick_flutter@1.1.3-dev.9
 - cherrypick_generator@2.0.0-dev.0
 - talker_cherrypick_logger@1.1.0-dev.0
2025-08-13 15:11:23 +03:00
..
2025-05-19 16:10:44 +03:00
2025-07-28 12:53:27 +03:00
2025-08-13 15:11:23 +03:00
2025-08-08 23:24:05 +03:00
2025-08-13 15:11:23 +03:00
2025-05-23 17:27:40 +03:00

cherrypick_annotations

License

A lightweight set of Dart annotations for dependency injection (DI) frameworks and code generation, inspired by modern approaches like Dagger and Injectable. Optimized for use with cherrypick_generator.


Features

  • @module Marks a class as a DI module for service/provider registration.
  • @singleton Declares that a method or class should be provided as a singleton.
  • @instance Marks a method or class so that a new instance is provided on each request.
  • @provide Marks a method whose return value should be registered as a provider, supporting DI into its parameters.
  • @named Assigns a string name to a binding for keyed resolution and injection.
  • @params Indicates that a parameter should be injected with runtime-supplied arguments.
  • @injectable Marks a class as eligible for automatic field injection. Fields annotated with @inject will be injected by the code generator.
  • @inject Marks a field to be automatically injected by the code generator.
  • @scope Declares the DI scope from which a dependency should be resolved for a field.

These annotations streamline DI configuration and serve as markers for code generation tools such as cherrypick_generator.


Getting Started

1. Add dependency

dependencies:
  cherrypick_annotations: ^latest

Add as a dev_dependency for code generation:

dev_dependencies:
  cherrypick_generator: ^latest
  build_runner: ^latest

2. Annotate your DI modules, providers, and injectable classes

Module and Provider Example

import 'package:cherrypick_annotations/cherrypick_annotations.dart';

@module()
abstract class AppModule {
  @singleton()
  Dio dio() => Dio();

  @named('baseUrl')
  String baseUrl() => 'https://api.example.com';

  @instance()
  Foo foo() => Foo();

  @provide()
  Bar bar(Foo foo) => Bar(foo);

  @provide()
  String greet(@params() dynamic params) => 'Hello $params';
}

With cherrypick_generator, code like the following will be generated:

final class $AppModule extends AppModule {
  @override
  void builder(Scope currentScope) {
    bind<Dio>().toProvide(() => dio()).singleton();
    bind<String>().toProvide(() => baseUrl()).withName('baseUrl');
    bind<Foo>().toInstance(foo());
    bind<Bar>().toProvide(() => bar(currentScope.resolve<Foo>()));
    bind<String>().toProvideWithParams((args) => greet(args));
  }
}

Field Injection Example

import 'package:cherrypick_annotations/cherrypick_annotations.dart';

@injectable()
class ProfileView with _$ProfileView{
  @inject()
  late final AuthService auth;

  @inject()
  @scope('profile')
  late final ProfileManager manager;

  @inject()
  @named('admin')
  late final UserService adminUserService;
}

The code generator produces a mixin (simplified):

mixin _$ProfileView {
  void _inject(ProfileView instance) {
    instance.auth = CherryPick.openRootScope().resolve<AuthService>();
    instance.manager = CherryPick.openScope(scopeName: 'profile').resolve<ProfileManager>();
    instance.adminUserService = CherryPick.openRootScope().resolve<UserService>(named: 'admin');
  }
}

Annotation Reference

@injectable

@injectable()
class MyWidget { ... }

Marks a class as injectable for CherryPick DI. The code generator will generate a mixin to perform automatic injection of fields marked with @inject().


@inject

@inject()
late final SomeService service;

Applied to a field to request automatic injection of the dependency using the CherryPick DI framework.


@scope

@inject()
@scope('profile')
late final ProfileManager manager;

Specifies the scope from which the dependency should be resolved for an injected field.


@module

@module()
abstract class AppModule {}

Use on classes to mark them as a DI module. This is the root for registering your dependency providers.


@singleton

@singleton()
Dio dio() => Dio();

Use on methods or classes to provide a singleton instance (the same instance is reused).


@instance

@instance()
Foo foo() => Foo();

Use on methods or classes to provide a new instance on each request (not a singleton).


@provide

@provide()
Bar bar(Foo foo) => Bar(foo);

Use on methods to indicate they provide a dependency to the DI module. Dependencies listed as parameters (e.g., foo) are resolved and injected.


@named

@named('token')
String token() => 'abc';

Assigns a name to a binding for keyed injection or resolution.
Can be used on both provider methods and fields.


@params

@provide()
String greet(@params() dynamic params) => 'Hello $params';

Indicates that this parameter should receive runtime-supplied arguments during dependency resolution.


License

Licensed under the Apache License 2.0.


Contributing

Pull requests and feedback are welcome!


Author

Sergey Penkovsky (sergey.penkovsky@gmail.com)