# Overview

## Scope

Scope provides Inversion of Control using the dependency injection (DI) pattern for Dart applications.

Scope allows you to inject values into a scope and then 'use' those dependencies from any method (or constructor) called within that scope.

Scope is not a replacement for the likes of Provider. Provider does dependency injection for your BuildContext whilst **Scope provides DI for your call stack.**

For Java developers, Scope provides similar functionality to a thread-local variables

Authors:&#x20;

* Philipp Schiffmann <philippschiffmann93@gmail.com>
* S. Brett Sutton

Scope is a reimagining of Philipp's zone\_id package. All credit goes to Phillipp's original implementation without which Scope wouldn't exist.

## Sponsored by OnePub

Help support Scope by supporting [OnePub](https://onepub.dev/drive/7e385313-5b0e-4874-b635-6098653a88f8), the private Dart repository.&#x20;

OnePub allows you to privately share Dart packages between your own projects or with colleagues.

Try it for free and publish your first private package in seconds.

| ![](https://975567146-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgkRTQ9hGOQKxkUlrKR2n%2Fuploads%2FoM2FrVEtDKaZXTCm8AhD%2Fimage.png?alt=media\&token=f6e9f035-847e-470c-9db0-ea891ba9cfb2) | <p>Publish a private package in five commands:</p><p><mark style="color:green;"><code>dart pub global activate onepub</code></mark></p><p><mark style="color:green;"><code>onepub login</code></mark></p><p><mark style="color:green;"><code>cd \<my package></code></mark></p><p><mark style="color:green;"><code>onepub pub private</code></mark> </p><p><mark style="color:green;"><code>dart pub publish</code></mark></p> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

Scope is available on pub.dev at:

{% embed url="<https://pub.dev/packages/scope>" %}

This is most easily understood via an example:

```dart
import 'package:scope/scope.dart';

/// create a key to access a scoped value
final ageKey = ScopeKey<int>();

void main() {
    /// create a Scope
    Scope()
    
    /// inject a value
    ..value<int>(ageKey, 18)
    
    /// run some code within the Scope
    ..run(() => a();
}
void a() => b();

/// `use` the injected value by its key 'ageKey'
void b() => print('You are ${use(ageKey)} years old');
```

We create a Scope within main and call the method `a()`  which calls `b()`. Both a() and b() are within the declared scope and therefore have access to the injected value `ageKey`.&#x20;

To access an injected value you call the `use` method.

## Inject multiple values of the same type

Scope allows you to inject multiple values of the same type

```dart
final ageKey = ScopeKey<int>();
final carKey = ScopeKey<Car>();
final otherCarKey = ScopeKey<Car>();

Scope()
..value<int>(ageKey, 18)
..value<Car>(carKey, new Car('red'))
..value<Car>(otherCarKey, new Car('blue'))
..run(() {
  print('age:  ${use(ageKey)} colour: ${use(carKey)} other: ${use(otherCarKey)}');
  // age: 18: colour: red other: blue
});
```

## Inject Single values and Sequences

You can inject values generated from a factory method as a `single` value or a `sequence` of values.

The difference between injecting a `single` value and a `value` is that the `single`'s factory method has access to all other values injected into the scope.

A `sequence` generates a new value each time the `use` method is called with its key.

```dart
import 'package:scope/scope.dart';
import 'package:money2/money2.dart';
final ageKey = ScopeKey<int>();
final seedKey = ScopeKey<String>();
final lotteryKey = ScopeKey<Money>();
Scope()
..value<int>(ageKey, 18)

/// call randomValue just once using ageKey as the seed.
..single<String>(seedKey, () => randomValue(use(ageKey))

/// call randomWinnings each time `use(lotteryKey)` is called.
..sequence<String>(lotteryKey, () => randomWinnings(use(seedKey))

..run(() {
  print('age:  ${use(ageKey)} you won: ${use(lotteryKey)}');
  // age: 18: you won: $2000.00
  
  Money randomWinnings(String seedValue) => ...

```

## Nesting

Scope also allows you to nest scopes to any level.

```dart
final ageKey = ScopeKey<int>();
final carKey = ScopeKey<Car>();
Scope()
..value<int>(ageKey, 18)
..value<Car>(carKey, new Car('red'))
..run(() {
    // use values the other scope
    print('age:  ${use(ageKey)} colour: ${use(carKey)}');
  // age: 18: colour: red

  // create a nested scope 
  Scope()
  ..value<Car>(carKey, new Car('green'))
  ..run(() {
    /// use values from the inner and outer scope.
    print('age:  ${use(ageKey)} colour: ${use(carKey)}');
   // age: 18: colour: green
  });
});

```
