2015-07-15 12 views
8

Birlik konteyneri, manuel kayıt gerekmeden kendiliğinden çözülebilen her türlü türü otomatik olarak çözecektir. Bu, bazı yönlerden iyidir, ancak sahip olduğum problem, bu tür bir çözünürlük için bir TransientLifetimeManager kullanmasıdır, neredeyse her zaman bir ContainerControlledLifetimeManager istiyorum. Yine de, türlerimi elle tekil olarak kaydedebilirim, ama unutursam, başlangıçta işlenmemiş bir istisna yerine, uygulama başarılı bir şekilde başlayacak ve her şey işe yarayacak. Ama sonuçta, bir tekil olması gereken bir tipin birden fazla örneği olduğu gerçeğinden dolayı, muhtemelen çok ince, teşhis edilmesi zor olan hatalar olacaktır.Birlik: Kapalı kayıtlar için varsayılan ömür boyu yöneticisini değiştirin ve/veya devre dışı bırakın

Benim soru: Ben türlerine kabı farklı bir varsayılan ömrü yöneticisini belirlemek veya tamamen varsayılan otomatik çözünürlük davranışını devre dışı bırakmak ve sınırlayabilir ya bir şekilde ben (doğrudan veya kendi anlaşmalarda) kendim kayıt var mı?

+0

Muhtemel http://stackoverflow.com/questions/29828410/default-the-lifetimemanager-to-the-singleton-manager-containercontrolledlifetim – gastonmancini

+0

Büyük; Bu varsayılan 'LifetimeManager' ayarlamak için bana bir yol veriyor gibi görünüyor. Otomatik/örtük kaydı da devre dışı bırakmanın bir yolu olup olmadığını bilmek isterim. – dlf

cevap

5

Ben farklı bir varsayılan ömür boyu yöneticisini

Evet, farklı bir ömür boyu yöneticisi kullanacak bir konteyner uzantısını kullanabilirsiniz belirtebilirsiniz ya bir yolu var mı. Örnek için Request for configurable default lifetimemanager'a bakın.

veya tamamen varsayılan otomatik çözünürlük davranışını devre dışı bırakmak ve türlerine kabı sınırlamak Kendimi

Evet, bir kap uzantısı yanı yapabilirsiniz kayıt olun.

İlk kayıt sırasında kayıt işleminin BuildKey kaydını kaydedin. Nesneyi oluşturmadan önce, BuildKey'in açık bir şekilde kaydedilmiş olup olmadığını kontrol edin.

public class RegistrationTrackingExtension : UnityContainerExtension 
{ 
    private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations = 
     new ConcurrentDictionary<NamedTypeBuildKey, bool>(); 

    protected override void Initialize() 
    { 
     base.Context.Registering += Context_Registering; 
     base.Context.Strategies.Add(
      new ValidateRegistrationStrategy(this.registrations), UnityBuildStage.PreCreation); 
    } 

    private void Context_Registering(object sender, RegisterEventArgs e) 
    { 
     var buildKey = new NamedTypeBuildKey(e.TypeTo, e.Name); 
     this.registrations.AddOrUpdate(buildKey, true, (key, oldValue) => true); 
    } 

    public class ValidateRegistrationStrategy : BuilderStrategy 
    { 
     private ConcurrentDictionary<NamedTypeBuildKey, bool> registrations; 

     public ValidateRegistrationStrategy(ConcurrentDictionary<NamedTypeBuildKey, bool> registrations) 
     { 
      this.registrations = registrations; 
     } 

     public override void PreBuildUp(IBuilderContext context) 
     { 
      if (!this.registrations.ContainsKey(context.BuildKey)) 
      { 
       Exception e = new Exception("Type was not explicitly registered in the container."); 
       throw new ResolutionFailedException(context.BuildKey.Type, context.BuildKey.Name, e, context); 
      } 
     } 
    } 
} 

Sonra uzantıyı ekleyin, bazı sınıfları kaydedin ve çözün. Sınıf açıkça kaydedilmemişse, istisna atılacaktır.

IUnityContainer container = new UnityContainer(); 
// Add container extension 
container.AddNewExtension<RegistrationTrackingExtension>(); 

// Register types 
container.RegisterType<MyClass>(); 
container.RegisterType<IMyClass, MyClass>(); 
container.RegisterType<IMyClass, MyClass>("A"); 

// These succeed because they were explicitly registered 
container.Resolve<IMyClass>(); 
container.Resolve<IMyClass>("A"); 
container.Resolve<MyClass>(); 

// MyClass2 was not registered so this will throw an exception 
container.Resolve<MyClass2>(); 
+1

Harika; Her iki çözüm de mükemmel çalışır. Ve 'RegistrationTrackingExtension' zaten uygulamada birkaç hata tespit etti! – dlf

1

DefaultLifetimeManegerExtension'ı denedim ancak bir şekilde işe yaramadı. (Belki Birlik değişti?). Yine de bir Uzantı kullanmak istemiyorsanız, RegsiterByConvention özelliğini de kullanabilirsiniz.

container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.None, WithName.Default, x => new DisposingTransientLifetimeManager()); 

Bu benim bir varsayılan olarak kullanmak seçti "DisposingTransientLifetimeManager" olan tüm Sınıfları kaydedecektir. Tüm kayıtların, aynı Tür ve Adın önceki kayıtlarının üzerine yazılacağından, bunu kayıtlarınızın başında yapmanız gerektiğini unutmayın.

İlgili konular