2013-01-23 38 views
7

我有两个范围,一个嵌套在另一个范围内。当我解决一个特定的服务时,我想要在一个根作用域中解析一个组件,并在子作用域中解析另一个组件。有没有一个简单的方法来做到这一点?用Autofac返回不同范围内的不同组件

我设法得到的东西用一个工厂类,确定当前范围是什么工作,然后返回相应的实例:

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属性来解决此问题,但这可能不是一个特别安全的事情。

回答

10

您可以在根容器中将FooInParentScope注册为SingleInstance。当创建内部生命周期时,将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>(); 
+2

这是一种处理它,我没有想到的方式。缺点是您必须在创建范围时进行一些额外的注册,而不是将它们全部集中在一个地方。 –