8

私には2つのスコープがあり、一方はもう一方の中にネストされています。特定のサービスを解決するとき、1つのコンポーネントを1つのルートスコープで解決し、別のコンポーネントを子スコープで解決したいと思います。これを行う簡単な方法はありますか?

現在のスコープが何であるかを決定するファクトリクラスを使用して何かを機能させ、適切なインスタンスを返すことができました。

IContainer BuildContainer()
{
    var builder = new ContainerBuilder();

    // ...
    builder.RegisterType<FooInParentScope>().AsSelf();
    builder.RegisterType<FooInChildScope>().AsSelf();
    builder.RegisterType<FooFactory>().AsImplementedInterfaces();
    builder.Register<IFoo>(c => c.Resolve<IFooFactory>().GetFoo()).InstancePerLifetimeScope();
    // ...
}


class FooFactory : IFooFactory
{
    private readonly ILifetimeScope m_scope;

    public FooFactory(ILifetimeScope scope)
    {
        m_scope = scope;
    }

    public IFoo GetFoo()
    {
        if (m_scope.Tag == "ParentScope")
            return m_scope.Resolve<FooInParentScope>();
        else
            return m_scope.Resolve<FooInChildScope>();
    }
}

class FooInParentScope : IFoo
{
}

class FooInChildScope : IFoo
{
}

このアプローチにはいくつかの問題があります。

  1. クラスを追加する必要があります(または2-IFooFactoryが本当に必要かどうかはわかりません)
  2. 上記のコードは、ParentScopeにネストされている他のスコープには対応していません。Autofac.Core.Lifetime.LifetimeScopeスコープをキャストしてプロパティを調べることでこれを修正できますParentLifetimeScopeが、それはおそらく特に安全なことではありません。
4

1 に答える 1

9

FooInParentScope をルート コンテナーに SingleInstance として登録できます。そして、内部lifetimescopeを作成するときに、FooInChildScopeの登録をSingleInstanceとして追加します(登録をオーバーライドします)。

builder.RegisterType<FooInParentScope>().As<IFoo>.SingleInstance();
var container = builder.Build();

var childScope = container.BeginLifetimeScope(innerBuilder =>
    {
        // override registration for IFoo in child lifetime scope:
        innerBuilder.RegisterType<FooInChildScope>().As<IFoo>().SingleInstance();
    });

FooInParentScope fooInParentScope = (FooInParentScope) container.Resolve<IFoo>();
FooInChildScope fooInChildScope = (FooInChildScope) childScope.Resolve<IFoo>();
于 2013-01-29T05:00:05.040 に答える