# Using

Once you create a `Scope` and inject `values` you can access those values from any method called within the context of the Scope.

By 'context' we mean any method that sits below the Scope's `run` method on the call stack:

```dart
import 'package:scope/scope.dart';
void httpRequestHandler(HttpRequest request)
{
    /// create a scope
    Scope()
        ..value<HttpRequest>(requestKey, request)
        ..value<int>(ageKey, 18)
        ..run(() => a());   /// call a() from within the scope
}

void a() => b();
void b() => c();

void c() {
    // c is within the scope, so we can call 'use' to access values
    // in the scope.
    print('Your are ${use(ageKey)} years old');
    
    print('Your ip is: ${use(requestKey).clientIp}');
}
```

You can see from the above example that the method `c` was call from `b` which was called from `a` which was called from the Scope's `run` method thus `c` is in the Scope's context.

Scope.run -> a ->b ->c

So a, b, and c are all within the Scope's context and have access to the Scope's values.

The `use` method provide access to injected values that exist in our scope **or any ancestors scope**.

To obtain an injected value we can call either of the two forms of `use`. The two forms are equivalent and exist simply for convenience.

```dart
     var age = use(ageKey);
     var name = Scope.use(ageKey);
```

The first version is concise whilst the second version provides better documentation.

ScopeKeys are typed and as such the result of `use` is also typed.

```dart
var ageKey = ScopeKey<int>();
var age = use(ageKey);
age is int;
```

### Missing ScopeKey

If you call `use(somekey)` and `somekey` hasn't been added to your Scope then a `MissingDependencyException` will be thrown.

You can avoid this problem using one of the following techniques:

### Default values

The most elegant method is to use a default.

You can set a default when:

* you create the scopeKey
* you call use

#### ScopeKey default

When creating a ScopeKey you can set a default value.

Any time `use` is called for that ScopeKey and the ScopeKey is not in Scope then the default will be returned.

The default is fixed for the life of the ScopeKey.

```dart
ScopeKey<int> countKey = ScopeKey.withDefault<int>(0);

count = use(countKey);

```

#### Use default

This is perhaps the most useful method as it allows you to provide a default value from where you call `use`.

```dart
final count = use(countKey, withDefault: () => nextCount++);
```

We use a lambda `() =>` for the default value to help with performance. The lambda provided to the `default` argument will only be called if the ScopeKey is missing. This allows the default to call a potentially long running method.

If the ScopeKey was created using `Scope.withDefault` and you call `use` with a default value then the default value provided to `use` will take precedence.

```dart
ScopeKey<int> countKey = ScopeKey.withDefault<int>(0);

count = use(countKey, withDefault: () => 1);
expect(count, equals(1));
```

#### hasScopeKey

Before calling `use` can test if the ScopeKey exists by calling `hasScopeKey()` or `Scope.hasScopeKey`

```dart
final int count;
if (hasScopeKey(countKey)) {
   count = use(countKey);
} else count = 1;
```

#### hasScopeValue

hasScopeValue works like `hasScopeKey` in that it checks if a key is in scope. The difference is that if the key isn't in scope but has a default value then `hasScopeValue` will return true.

```dart
final countKey = ScopeKey.withDefault<int>(10);
final int count;
if (hasScopeValue(countKey)) {
   count = use(countKey);
} else count = 20;

expect(count, equals(10));
```

#### isWithinScope

You can check if you are within a Scope by calling `isWithinScope()` or `Scope.isWithinScope().`

This method isn't very reliable as it may turn out that you are running in someone else's scope.

```dart
final int count;
if (isWithinScope()) {
   count = use(countKey);
} 
else count = 1;
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://scope.onepub.dev/fundamentals/scope/using.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
