2017-07-31 1 views
1

J'ai un hirerachy de classe qui ressemble à ceci:Comment puis-je résoudre un service via une fabrique de délégués avec un décorateur conditionnel?

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; 
} 

Notez que Bar prend Func<IFoo> au lieu de IFoo directement à cause de la dépendance circulaire lors de la résolution de IFoo.

Mon inscription actuelle ressemble aime ceci:

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"); 
    } 
} 

Je voudrais enregistrer conditionnellement BazDecorator que lors de la résolution par Foomais pasFunc<IFoo> comme:

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

Comment puis-je enregistrer mes services dans AutoFac?

Répondre

2

Vous devez enregistrer votre Func<IFoo> manuellement, pour transmettre des paramètres appropriés explicitement aux Foo et Bar composants

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

Si vous ne voulez pas « nouveau » Foo et Bar l'intérieur Register fonction, il pourrait aussi être obtenu en les résolvant à partir du conteneur, mais le code semble plutôt méchant:

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

Est-ce que cela peut être évité? Puisque dans mon code actuel, 'Baz' et' BazDecorator' sont réellement très profonds dans le graphe d'objet, je voudrais éviter d'enregistrer explicitement une grande partie de mon graphe d'objet si possible. – rexcfnghk

+0

Désolé, je ne peux pas penser à une autre solution avec moins de code ou en changeant votre code original ... – tdragon

+0

C'est bon, merci pour votre contribution de toute façon! – rexcfnghk