# Registry

## About

A well known object *(known by all)*, useful for locating other objects/services.

{% hint style="info" %}
**You can use a Registry to inject dependencies.**

**Why use this:**

* *In Typescript you can inject dependencies by passing the dependent classes as parameters to* `constructors`*, but this increases coupling, since any changes at the* `constructor` `parameters` *will break code everywhere you instanciate this Class.*
* *Also, using a* `Registry` *will significantly reduce the amount of classes passed to constructors.*
* *And it will centralize all dependencies in a single* `Registry` *class. (Could be a downside)*
  {% endhint %}

{% hint style="success" %}
`Registry` Pattern is very important for `Dependency Injection`.

Serves basically as a Dependency pool.
{% endhint %}

## Implementing using Singleton

{% code title="Registry.ts" %}

```typescript
export default class Registry {
    private dependencies: {[name: string]: any} = {};
    private static instance: Registry;
    
    private constructor() {}
    
    provide(name: string, dependency: any) {
        this.dependencies[name] = dependency;
    }
    
    inject(name: string) {
        return this.dependencies[name];
    }
    
    static getInstance() {
        if (!Registry.instance) Registry.instance = new Registry();
        return Registry.instance;
    }
}
```

{% endcode %}

Use it anywhere on the code to, provide *(create)* and inject *(get)* other class instances *(dependencies)*.

## Example (without `decorators`)

#### This

{% code title="main.ts" %}

```typescript
const userDAO = new UserDAO();
new Signup(userDAO);
```

{% endcode %}

{% code title="Signup.ts" %}

```typescript
class Signup {
    constructor (private readonly userDAO: UserDAO) {}
    
    execute(value: string) {
        this.userDAO.getUserByID(value);
    }
}
```

{% endcode %}

#### Will be substituted by

In the `main.ts` we instanciate and provide to the `Registry` all the classes we want.

{% code title="main.ts" %}

```typescript
// This will automatically create Registry instance, and set the userDAO instance
Registry.getInstance().provide('userDAO', new UserDAO());
```

{% endcode %}

At the `Signup.ts` for example we will grab the `UserDAO` instance created in the `main.ts`. And as you can see, no classes had to be passed to the constructor as parameter.

{% code title="Signup.ts" %}

```typescript
class Signup {
    userDAO?: UserDAO;

    constructor () {
        this.userDAO = Registry.getInstance().inject('userDAO');
    }
    
    execute(value: string) {
        this.userDAO?.getUserByID(value);
    }
}
```

{% endcode %}

## Example (with `decorators`) (`in typescript`)

{% hint style="info" %}
To work with decorators, we need also to lazy load `Signup` calls to `getUserByID` with the  [Broken link](https://kdongs.gitbook.io/kdocs/design-patterns/broken-reference "mention").
{% endhint %}

The same example above, will be substituted by:

{% code title="Registry.ts" %}

```typescript
export default class Registry {
    // The same as above
}

// decorator for Registry
export function inject(name: string) {
    return function(target: any, propertyKey: string) {
        target[propertyKey] = new Proxy({}, {
            get(target: any, propertyKey: string) {
                const dependency = Registry.getInstance().inject(name);
                return dependency[propertyKey];
            }
        });
    }
}
```

{% endcode %}

{% code title="main.ts" %}

```typescript
// This will automatically create Registry instance, and set the userDAO instance
Registry.getInstance().provide('userDAO', new UserDAO());
```

{% endcode %}

{% code title="Signup.ts" %}

```typescript
import { inject, Registry } from 'Regestry';

class Signup {
    @inject('userDao')
    userDAO?: UserDAO;
    
    execute(value: string) {
        this.userDAO?.getUserByID(value);
    }
}
```

{% endcode %}
