VContainer入門(3) - 基本的なRegister

# この記事について
[前回](https://qiita.com/sakano/items/e38306a8204c531a40c1)に引き続きVContainerの説明をしていきます。

これから何回かにわけて`IContainerBuilder`で使える様々なRegister関連のメソッドを紹介します。

今回は基本的なRegisterについて説明します。
MonoBehaviour関連のRegisterの説明は[次回](https://qiita.com/sakano/items/7951049b18b8a4a0e3dd)にします。

目次ページ: [VContainer入門](https://qiita.com/sakano/items/b91e01f7fc0a946090ac)




## Register

### 基本的な使い方
`Register`は一番基本的な登録メソッドです。

型引数に登録したいクラス、引数にLifetimeScopeを指定するだけで使えます。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton);
```
```cs:受け取る
[Inject]
public Constructor(Logger logger) { }
```

### 登録する型を指定する
型引数にインターフェースを指定して別の型として登録できます。
受け取る側は具体的な型を意識せずにインターフェースとして受け取れるようになります。

```cs:登録する
builder.Register<ILogger, Logger>(Lifetime.Singleton);
```
```cs:受け取る
[Inject]
public Constructor(ILogger logger) { }
```

### 生成方法を指定する
登録する型のオブジェクトを生成するデリゲートを指定して、その型の生成方法を指定できます。

IObjectResolverを受け取って登録する型を返すデリゲートを渡します。
その型を解決するときはそのデリゲートが呼ばれるようになります。

```cs:登録する
builder.Register<ILogger>(resolver => new Logger(), Lifetime.Singleton);
```
```cs:受け取る
[Inject]
public Constructor(ILogger logger) { }
```




## RegisterFactory

### 基本的な使い方
`RegisterFactory`でファクトリメソッドを登録できます。

ここで言うファクトリメソッドとは、その型のオブジェクトを生成するメソッドです。
そのメソッドを受け取った側でそれを呼び出して必要なオブジェクトを生成できます。

```cs:登録する
builder.RegisterFactory<ILogger>(() => new Logger());
```
```cs:受け取る
[Inject]
public Constructor(System.Func<ILogger> loggerFactory)
{
    ILogger logger = loggerFactory.Invoke();
}
```

### 引数ありで登録する
型引数に指定して引数ありのファクトリメソッドも登録できます。

以下の例では引数としてintを受け取っています。
型引数に複数指定して複数の引数にも対応できます。

```cs:登録する
builder.RegisterFactory<int, ILogger>(arg => new Logger(arg));
```
```cs:受け取る
[Inject]
public Constructor(System.Func<int, ILogger> loggerFactory)
{
    ILogger logger1 = loggerFactory.Invoke(1);
    ILogger logger2 = loggerFactory.Invoke(2);
}
```




## RegsiterInstance

### 基本的な使い方
`Register`で型を登録すると、その型が必要になったときにVContainer側で生成されます。
一方、`RegisterInstance`を使うとすでに存在するインスタンスを登録できます。

```cs:登録する
var logger = new Logger();
builder.RegisterInstance(logger);
```
```cs:受け取る
[Inject]
public Constructor(Logger logger) { }
```

### 登録する型を指定する
`Register`と同じように登録する型を指定できます。

```cs:登録する
var logger = new Logger();
builder.RegisterInstance<ILogger>(logger);
```
```cs:受け取る
[Inject]
public Constructor(ILogger logger) { }
```




## As

### As
Asを使うと登録するインターフェースの型を指定できます。Registerの後ろにメソッドチェーンの形で使います。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton).As<ILogger>();
```
```cs:受け取る
[Inject]
public Constructor(ILogger logger) { }
```

複数の型で登録したい場合はつなげて指定できます。
指定したどの型でも受け取れるようになります。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton).As<ILogger>().As<ILogger2>.As<ILogger3>();
```
```cs:受け取る
[Inject]
public Constructor(ILogger logger, ILogger2 logger2, ILogger3 logger3) { }
```

### AsSelf
インターフェースとして登録するとき、さらに自分自身の型としても登録したい場合は`AsSelf()`をつけます。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton).As<ILogger>().AsSelf();
```
```cs:受け取る
[Inject]
public Constructor(Logger logger, ILogger logger) { }
```

### AsImplementedInterfaces
`AsImplementedInterfaces()`で、その型が実装する全てのインターフェースとして登録できます。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton).AsImplementedInterfaces();
```




## WithParameter
WithParameterを使うと、そのRegisterで生成されるオブジェクトに対してだけinjectできます。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton).WithParameter<string>("[Prefix]");
```

このように登録するとLoggerでstringが受け取れるようになります。

```cs:Logger.cs
public sealed class Logger
{
    private string prefix;

    [Inject]
    public void Logger(string prefix)
    {
        this.prefix = prefix;
    }

    public void Log(string message) => Debug.Log(prefix + message);
}
```

WithParameterでは名前でもinjectできます。

```cs:登録する
builder.Register<Logger>(Lifetime.Singleton)
    .WithParameter("prefix", "[Prefix]")
    .WithParameter("suffix", "[Suffix]");
```

```cs:Logger.cs
public sealed class Logger
{
    private string prefix;
    private string suffix;

    [Inject]
    public void Logger(string prefix, string suffix)
    {
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public void Log(string message) => Debug.Log(prefix + message + suffix);
}
```