2013-02-03 11 views
6

Ich hätte gern eine Instanz pro passender lebenslanger Bereichsregistrierung in Autofac, muss aber gelegentlich eine Instanz von einem globalen Container anfordern (wo es keinen passenden lebenslangen Bereich gibt). In Szenarien, in denen kein passender Lifetime-Bereich vorhanden ist, möchte ich eine Instanz auf oberster Ebene angeben, anstatt eine Ausnahme auszulösen.Instanz pro übereinstimmendem Gültigkeitszeitraum, mit Standard?

Ist das möglich?

+0

Warum brauchen Sie das? Möchten Sie, dass die globale Registrierung von der Bereichsregistrierung abweicht? Oder möchten Sie, dass Verbraucher in einem Fall eine Instanz und in anderen Fällen andere Instanzen erhalten, während die Konfigurationen sowohl für den globalen als auch für den markierten Bereich gleich bleiben? –

+0

@PavelGatilov Letzteres. Gleiche Konfiguration, unterschiedliche Instanz für jeden markierten Bereich und unterschiedliche Instanz für globalen Bereich. –

Antwort

9

Ich glaube, Sie besser Autofac verlängern würde durch eine neue Lebensdauer Option einzuführen. Ich nahm die Autofac Quellen und modifiziert sie ein wenig:

public static class RegistrationBuilderExtensions 
{ 
    public IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerMatchingOrRootLifetimeScope(this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, params object[] lifetimeScopeTag) 
    { 
     if (lifetimeScopeTag == null) throw new ArgumentNullException("lifetimeScopeTag"); 
     builder.RegistrationData.Sharing = InstanceSharing.Shared; 
     builder.RegistrationData.Lifetime = new MatchingScopeOrRootLifetime(lifetimeScopeTag); 
     return builder; 
    } 
} 

public class MatchingScopeOrRootLifetime: IComponentLifetime 
{ 
    readonly object[] _tagsToMatch; 

    public MatchingScopeOrRootLifetime(params object[] lifetimeScopeTagsToMatch) 
    { 
     if (lifetimeScopeTagsToMatch == null) throw new ArgumentNullException("lifetimeScopeTagsToMatch"); 

     _tagsToMatch = lifetimeScopeTagsToMatch; 
    } 

    public ISharingLifetimeScope FindScope(ISharingLifetimeScope mostNestedVisibleScope) 
    { 
     if (mostNestedVisibleScope == null) throw new ArgumentNullException("mostNestedVisibleScope"); 

     var next = mostNestedVisibleScope; 
     while (next != null) 
     { 
      if (_tagsToMatch.Contains(next.Tag)) 
       return next; 

      next = next.ParentLifetimeScope; 
     } 

     return mostNestedVisibleScope.RootLifetimeScope; 
    } 
} 

Fügen Sie einfach diese Klassen zu einem Projekt und registrieren Sie Komponente wie:

builder.RegisterType<A>.InstancePerMatchingOrRootLifetimeScope("TAG"); 

ich es selbst nicht ausprobiert haben, aber es sollte funktionieren .

2

Eine mögliche Lösung besteht darin, die Registrierung im Gültigkeitsbereich für Kinder zu überschreiben.

Probe:

public enum Scopes 
{ 
    TestScope 
} 

public class Test 
{ 
    public string Description { get; set; } 
} 

public class Tester 
{ 
    public void DoTest() 
    { 
     ContainerBuilder builder = new ContainerBuilder(); 
     builder.RegisterType<Test>() 
      .OnActivating(args => args.Instance.Description = "FromRoot") 
      .SingleInstance(); 
     var container = builder.Build(); 

     var scope = container.BeginLifetimeScope(Scopes.TestScope, b => b 
      .RegisterType<Test>() 
      .InstancePerMatchingLifetimeScope(Scopes.TestScope) 
      .OnActivating(args => args.Instance.Description = "FromScope")); 

     var test1 = container.Resolve<Test>(); 
     Console.WriteLine(test1.Description); //writes FromRoot 

     var test2 = scope.Resolve<Test>(); 
     Console.WriteLine(test2.Description); //writes FromScope 

     Console.ReadLine(); 
    } 
} 
+0

Während der Code ein wenig verwirrend ist, hat @Memoizer Recht - der einzige Weg dies zu tun ist, die Registrierung im untergeordneten Bereich zu überschreiben. Leider lautet die Frage "Ich möchte einen lebenslangen Oszilloskop-Stil an einem Ort und einen anderen Stil an einem anderen Ort", was kein unterstütztes Szenario ist. Daher bedarf es einiger benutzerdefinierter Codes, um dies zu ermöglichen. –