2017-07-31 17 views
1

我有一個類hirerachy,看起來像這樣:如何使用條件裝飾器通過委託工廠解析服務?

public class Foo : IFoo 
{ 
    private readonly IBar _bar; 

    public Foo(IBar bar) 
     => _bar = bar; 
} 

public class Bar : IBar 
{ 
    private readonly Func<IFoo> _fooFunc; 
    private readonly IBaz _baz; 

    public Bar(Func<IFoo> fooFunc, IBaz baz) 
    { 
     _fooFunc = fooFunc; 
     _baz = baz; 
    } 
} 

public class Baz : IBaz 
{ 
} 

public class BazDecorator : IBaz 
{ 
    private readonly IBaz _decoratee; 

    public BarDecorator(IBaz decoratee) 
     => _decoratee = decoratee; 
} 

注意Bar解決了IFoo時需要Func<IFoo>,而不是直接IFoo由於循環依賴的。

我目前的註冊看起來喜歡這樣的:

public class MyModule : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<Foo>().As<IFoo>(); 

     builder.RegisterType<Bar>().As<IBar>(); 

     // Func<IFoo> is automatically resolved in AutoFac 

     builder.RegisterType<Baz>().Named<IBaz>("baz"); 

     builder.RegisterDecorator<IBaz>((c, inner) => 
      new BazDecorator(inner), 
      fromKey: "baz"); 
    } 
} 

我想只有有條件註冊BazDecorator通過Foo但不Func<IFoo>像解決時:

Foo------Bar-----BazDecorator----Baz 
      \ 
      \ 
      \____Foo----Bar----Baz 

我如何註冊我的服務在AutoFac中?

回答

2

您需要手動註冊Func<IFoo>,明確地傳遞正確的參數到FooBar組件

builder.Register<Func<IFoo>>(c => 
    { 
     var ctx = c.Resolve<IComponentContext>(); 
     return() => new Foo(new Bar(() => ctx.Resolve<IFoo>(), ctx.ResolveNamed<IBaz>("baz"))); 
    }); 

如果你不想「新」 FooBarRegister功能,它也可以通過解決它們從容器中實現,但代碼看起來相當討厭:

builder.Register<Func<IFoo>>(c => 
    { 
     var ctx = c.Resolve<IComponentContext>(); 
     return() => ctx.Resolve<IFoo>(
      new ResolvedParameter(
       (p, cx) => p.Name == "bar", 
       (p, cx) => cx.Resolve<IBar>(new ResolvedParameter(
        (p1, c1) => p1.Name == "baz", 
        (p1, c1) => c1.ResolveNamed<IBaz>("baz"))))); 
    }); 
+0

這可以避免嗎?因爲在我的實際代碼中,'Baz'和'BazDecorator'實際上在對象圖中非常深,所以我想盡可能避免顯式註冊我的對象圖的大部分。 – rexcfnghk

+0

對不起,我不能想到任何其他解決方案將需要更少的代碼或更改您的原始代碼... – tdragon

+0

沒關係,感謝您的輸入無論如何! – rexcfnghk