2013-02-03 31 views
6

Autofac uygulamasında ömür boyu kapsama alanıyla eşleşen bir kayıt için bir örneğe sahip olmak istiyorum, ancak bazen bir global kapsayıcıdan (eşleşen ömür boyu kapsam bulunmayan) bir örnek istemeniz gerekir. Eşleşen yaşam boyu kapsamının olmadığı senaryolarda, bir istisna atmak yerine en üst düzey bir örnek vermek istiyorum.Eşleşen ömür boyu kapsam başına örnek, varsayılan olarak mı?

Bu mümkün mü?

+0

Neden buna ihtiyacınız var? Global kaydın kapsam kaydından farklı olmasını ister misiniz? Ya da yapılandırmalar, hem global kapsam hem de etiketli kapsam için aynı kalırken, tüketicilerin bir durumda bir örneği ve diğer durumlarda diğer örnekleri almasını ister misiniz? –

+0

@PavelGatilov İkincisi. Aynı yapılandırma, etiketli kapsam başına farklı örnek ve genel kapsam için farklı örnek. –

cevap

9

sana daha iyi bir yeni ömür boyu seçeneği sunarak AutoFac uzatmak düşünüyorum. Ben Autofac kaynaklar aldı ve onları biraz modifiye:

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

Sadece proje için bu sınıfları ekleyin ve kayıt Bileşen olarak: Ben kendim denemedim

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

, ancak çalışması gerekir .

2

Olası çözüm, çocuk yaşamı kapsamındaki kaydı geçersiz kılmaktır.

Örnek:

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

Kod biraz kafa karıştırıcı olsa da, @Memoizer doğrudur - bunu yapmanın tek yolu, çocuk kapsamındaki kaydı geçersiz kılmaktır. Ne yazık ki, sorulan soru, "Bir yaşam boyu kapsama stilini tek bir yerde ve farklı bir yerde farklı bir yerde istiyorum", ki bu desteklenen bir senaryo değil, bunun gerçekleşmesi için bazı özel kodlar gerektiriyor. –

İlgili konular