2017-04-02 1 views
0

Lors de l'évaluation Func<T> où T est enregistré avec InstancePerMatchingLifetimeScope, dans une classe singleton, ne devrait-il pas fournir la même instance? c'est-à-dire, ne devrait pas Func<T> être "conscient de la portée"?Autofac Func <T> avec InstancePerMatchingLifetimeScope

Peut-être qu'un exemple serait meilleur.

J'ai deux classes:

class MyScoped 
    { 
     public int Num { get; set; } 
    } 

    class MySingleton 
    { 
     readonly Func<MyScoped> scoped; 

     public MySingleton(Func<MyScoped> scoped) 
     { 
      this.scoped = scoped; 
     } 

     public void Do() 
     { 
      var scopedObj = scoped(); 

      Console.WriteLine(scopedObj.Num); 
     } 
    } 

qui sont enregistrées comme ceci:

 var builder = new ContainerBuilder(); 

     builder.RegisterType<MyScoped>().InstancePerMatchingLifetimeScope("MyScope", "root"); 
     builder.RegisterType<MySingleton>().SingleInstance(); 

     var container = builder.Build(); 

Et je courais le morceau de code suivant:

 var singleton = container.Resolve<MySingleton>(); 

     singleton.Do(); 

     using (var scope = container.BeginLifetimeScope("MyScope")) 
     { 
      var scoped = scope.Resolve<MyScoped>(); 

      scoped.Num = 1; 

      singleton.Do(); 
     } 

je me attends que le premier appel à Do() afficherait 0, et le second imprimerait 1.

je devais changé MySingleton pour InstancePerDependency il donc travailler, ce qui est une mauvaise solution pour moi, parce que MySingleton peut être coûteux à créer.

Qu'est-ce qui me manque ici?

+0

C'est le comportement normal. Vous enregistrez 'MyScoped' avec' InstancePerMatchingLifetimeScope' de "MyScope" puis "root". * Autofac * recherchera d'abord le premier cycle de vie correspondant qui est "MyScope" puis verra s'il y a une instance de MyScoped dans cette portée. Sinon, il va en créer un nouveau. Si vous supprimez "MyScope" dans votre déclaration 'InstancePerMatchingLifetimeScope', cela fonctionnera comme prévu. Pourriez-vous nous expliquer ce que vous essayez de faire? –

Répondre

0

Il semble que les services enregistrés en tant qu'instance unique soient résolus dans le contexte de la portée racine. Cela signifie que votre Func<MyScoped> injecté à MySingleton résoudrait toujours MyScoped depuis la racine. Le code suivant:

var singleton = container.Resolve<MySingleton>(); 
var s = container.Resolve<MyScoped>(); 

s.Num = 1; 

singleton.Do(); 

using (var scope = container.BeginLifetimeScope("MyScope")) 
{ 
    var scoped = scope.Resolve<MyScoped>(); 

    scoped.Num = 10; 

    singleton.Do(); 
} 

imprimerait 1 deux fois, parce que var scopedObj = scoped(); dans Do() méthode résoudrait MyScoped du conteneur racine, pas du champ d'application.

Vous pouvez obtenir ce que vous voulez en passant la dépendance nécessaire manuellement dans Do() méthode:

class MySingleton 
{ 
    public void Do(MyScoped myScoped) 
    { 
     Console.WriteLine(myScoped.Num); 
    } 
} 

// ... 

var singleton = container.Resolve<MySingleton>(); 
var s = container.Resolve<MyScoped>(); 

s.Num = 1; 

singleton.Do(s); 

using (var scope = container.BeginLifetimeScope("MyScope")) 
{ 
    var scoped = scope.Resolve<MyScoped>(); 

    scoped.Num = 10; 

    singleton.Do(scoped); 
} 

Il imprimerait 1 et 10 respectivement.

+0

Malheureusement, ce n'est pas une bonne solution IMO. Cela m'obligerait à coupler la dépendance dans toute la pile. – Elad