Autofac について調べてみた　その２ インスタンスのスコープ補足

[Autofac について調べてみた　その１ インスタンスのスコープ](http://qiita.com/TsuyoshiUshio@github/items/f4d83c76520a86c028dc[)で、不明だった点に関して師匠が答えてくれたので、私も検証してみた。

# Instance Per Own のスコープの未解決事項

[Instance Per Own　未解決事項](http://qiita.com/TsuyoshiUshio@github/items/f4d83c76520a86c028dc#instance-per-owned-%E6%9C%AA%E8%A7%A3%E6%B1%BA%E4%BA%8B%E9%A0%85)　で書いた通り、実行結果が、普通のインジェクションにしても変わらなかったので、なんでこの書き方で書くのだろうと思ったのでそれを理解したかった。

```csharp

using Autofac;
using Autofac.Features.OwnedInstances;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PerOwned
{
    class Program
    {
        static void Main(string[] args)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<Backend>().AsImplementedInterfaces().InstancePerOwned<Command>();
            builder.RegisterType<Command>();
            var container = builder.Build();

            using (var scope = container.BeginLifetimeScope()) // using は 変数の Dispose() を呼ぶ
            {
                Console.WriteLine("BeginLifetimeScope");
                using (var command = scope.Resolve<Owned<Command>>())
                {
                    command.Value.Execute();
                }

                using (var command = scope.Resolve<Owned<Command>>())
                {
                    command.Value.Execute();
                }
                Console.WriteLine("EndLifetimeScope");
            }
            Console.ReadLine();
           

        }
    }

    interface IBackend
    {
        string Id { get; }
    }
    class Backend: IBackend, IDisposable
    {
        public string Id { get; } = Guid.NewGuid().ToString();
        public void Dispose()
        {
            Console.WriteLine($"Backend#Dispose is called. InstanceId: {Id}");
        }
    }

    class Command
    {
        private IBackend Backend { get; }
        public Command(IBackend backend)
        {
            this.Backend = backend;
        }
        public void Execute()
        {
            Console.WriteLine($"Command#Execute is called with Backend {Backend.Id}");
        }
    }
}

```

ポイントはこちらだ。

```csharp
builder.RegisterType<Backend>().AsImplementedInterfaces().InstancePerOwned<Command>();
builder.RegisterType<Command>();
```
新しい書き方になっているが、`builder.RegisterType<Backend>().As<IBackend>() ...` と変わらない。直接指定しないのでこちらのほうがカッコいい。ポイントは、Command -> IBackend の依存性がある場合、`Command#Dispose()` が呼ばれると、`Backend#Dispose` も勝手に呼ばれるようになるのである。コードを見てわかるとおり、Command には`Dispose()` のコードは書いていない。これを `Owned` がラップしてくれている。

[こちらの記事](https://nblumhardt.com/2011/01/an-autofac-lifetime-primer/)が詳しい。自分がわからなかったことも、師匠にかかれば一撃で解決してしまう。凄いものだ。

ちなみに、Owned を書かないやり方でもきっと同じことができるが面倒だ。例えば、 次のようなコードを書くとこの時点でエラーになる。何故かというと、using を使うためには、Dispose() が必要だが、Command に書いていないからだ。Command に Dispose() を書いてその中で、Backend の Dispose() を呼ぶようなコードを書いてあげればそれでいいと思うが、そういうことは、この書き方だとする必要がなくなる。

```csharp

            builder = new ContainerBuilder();
            builder.RegisterType<Backend>().AsImplementedInterfaces();
            builder.RegisterType<Command>();
            container = builder.Build();

            using (var scope = container.BeginLifetimeScope())
            {
                Console.WriteLine("BeginLifetimeScope without Owned class");
                using (var command = scope.Resolve<Command>()) // ここでエラーになる
                {

                }
            }
```

実行結果はこのとおり

```
BeginLifetimeScope
Command#Execute is called with Backend e84d604d-d902-4929-aa3b-72ad3b2a477c
Backend#Dispose is called. InstanceId: e84d604d-d902-4929-aa3b-72ad3b2a477c
Command#Execute is called with Backend 803b0570-fd63-4b63-96ed-bb2ec5e103f2
Backend#Dispose is called. InstanceId: 803b0570-fd63-4b63-96ed-bb2ec5e103f2
EndLifetimeScope
```
Command のライフサイクルで、Backend が作られて、Command が消されたら、Backend も消されている。