8

Bu yüzden DI/IoC Kapsayıcım OpenNETCF.IoC üzerinde çalışıyorum ve kapsayıcı koleksiyonlarda kimliği değiştirilebilen öğeler için bir tür yaşam döngüsü yönetimi eklemek için bir (makul) özellik isteğim var.DI: Tek Kullanımlık Nesnelerin Kullanım Süreci

Şu anki düşüncem şu: Bir nesneyi yok edip edilmediğini görmek için bir nesneyi sorgulayamadığımdan ve ne zaman kullanıma sunulduğuna ilişkin bir olay alamıyorum, nesneler için bir çeşit sarıcı oluşturmam gerekiyor Bir geliştiricinin çerçeveyi yönetmesini istiyor. kuyu

public TTypeToBuild AddNew<TTypeToBuild>() { ... } 

Ne yeni bir yöntem ekliyor düşünüyorum (: Şu anda AddNew (basitlik uğruna sadece bir aşırı yük var ve hiçbir ekleme yoktur varsayıyoruz) ile eklenebilir nesnelerin

bunlardan grup, ama siz) resim elde:

public class DisposableWrappedObject<T> 
    where T : class, IDisposable 
{ 
    public bool Disposed { get; private set; } 
    public T Instance { get; private set; } 

    internal event EventHandler<GenericEventArgs<IDisposable>> Disposing; 

    internal DisposableWrappedObject(T disposableObject) 
    { 
     if (disposableObject == null) throw new ArgumentNullException(); 

     Instance = disposableObject; 
    } 

    ~DisposableWrappedObject() 
    { 
     Dispose(false); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     lock(this) 
     { 
      if(Disposed) return; 

      EventHandler<GenericEventArgs<IDisposable>> handler = Disposing; 
      if(handler != null) 
      { 
       Disposing(this, new GenericEventArgs<IDisposable>(Instance)); 
      } 

      Instance.Dispose(); 

      Disposed = true; 
     } 
    } 
} 
: DisposableWrappedObject şöyle

public DisposableWrappedObject<IDisposable> AddNewDisposable<TTypeToBuild>() 
    where TTypeToBuild : class, IDisposable 
{ 
    ... 
} 

Şimdi, bir öğeye AddNewDIsposable aracılığıyla konteynere eklendiğinde, bir eventhandler de eklenir, böylece Dispose (wrapper aracılığıyla) alındığında çerçeve onu alttaki koleksiyondan kaldırır.

Aslında bunu uygulamıştım ve birim testlerini geçiyor, ancak bunun nerede kırılabileceğine veya tüketici geliştiricisine nasıl daha "dost" hale getirilebileceğine dair fikirler arıyorum.

private object AddNew(Type typeToBuild, string id, bool wrapDisposables) 
{ 
    .... 

    object instance = ObjectFactory.CreateObject(typeToBuild, m_root); 

    if ((wrapDisposables) && (instance is IDisposable)) 
    { 
     DisposableWrappedObject<IDisposable> dispInstance = new 
       DisposableWrappedObject<IDisposable>(instance as IDisposable); 
     dispInstance.Disposing += new 
       EventHandler<GenericEventArgs<IDisposable>>(DisposableItemHandler); 
     Add(dispInstance as TItem, id, expectNullId); 
     instance = dispInstance; 
    } 

    .... 

    return instance; 
} 

private void DisposableItemHandler(object sender, GenericEventArgs<IDisposable> e) 
{ 
    var key = m_items.FirstOrDefault(i => i.Value == sender).Key; 
    if(key == null) return; 
    m_items.Remove(key); 
} 
+0

biz ekleniyor özelliğin daha eksiksiz açıklamalar alabilir miyim? İnsanların bunu istediği kullanım durumları nelerdir, (IoC çerçevesi) veya son kullanıcı olarak sizin için olay işleyicisidir? Vb .. – Quibblesome

+0

Kullanım durumu otomatik yaşam döngüsü yönetimi eklemektir. Bir koleksiyona bir tek kullanımlık öğe eklediyseniz ve daha sonra da Atla'yı çağırınsanız, kapsayıcının nesneye bir kökü tutacağı için asla temizlenmeyecektir. Buradaki fikir, onu bulmak için koleksiyona geri dönmek zorunda kalmadan Nesne üzerine At'ı çağırabilmeniz ve otomatik olarak, konteyner koleksiyonundan kaldırılmasına neden olmanızdır. Olay, yalnızca çerçeve tarafından dahili olarak kullanılır (hatta dışarıda kullanılmamak için dahili olarak işaretlenir) ve işleyici onu toplamadan çıkarır. – ctacke

+0

Açıklık için olay işlemeyi eklemek için bu soruyu güncelledim. – ctacke

cevap

3

Belki bir şey eksik ama:

DÜZENLEME 1 Atılması olay nasıl kullanıldığına bir soru olmadığı için

, burada bazı kod (önemli olan şeylere kesilmiş) API'ye neden yeni yöntemler ekliyorsunuz? Bir nesneyi kapsayıcıya eklendiğinde, kimliğine uygun olup olmadığını kontrol edip, uygun şekilde işlemek için gönderilebilir.

Ayrıca yıkıcıya ihtiyacınız olup olmadığını da merak ediyorum. Konteynerin IDisposable olduğu varsayılırsa (Unity's gibi), sadece Basic Dispose Pattern'u uygulayabilir ve çok fazla GC yükünü kaydedebilirsiniz.

geçerli olabilecek bazı sorular

:

+0

Ah, ama bir kadro ile, o zaman ne? Kimliğin kabul edilebilir olduğunu ve bir konteynere konması gerektiğini biliyorum, ancak AddNew <> yönteminin giriş türünü döndürmesi gerektiğinden, söz konusu kapsayıcıyı iade edemiyorum. Nesneyi doğrudan API'nin istediği gibi döndürürsem, bunların sarılmış olduğunu bilmezler ve ardından örneği değil, atın üzerine At'ı çağırın ve yine GC'ed'i almayan Diske alınan nesneleri tutma sorunum olur. – ctacke

+5

@ctacke: Tüketicilerin IoC ile oynadıklarında takip etmeleri gereken bazı kurallar var: * DI oluşturma nesnesini * DI kapsayıcısına yüklediğinizde, * tüm * ömür boyu yönetimini, * imha örnekleri de dahil olmak üzere devretmeniz gerekir. . Bu nedenle, tüketiciler tarafından enjekte edilen bağımlılığı erken boşaltırlarsa, bu durum birden fazla tüketici arasında paylaşılabileceğinden dolayı bir hata olur. Sadece yanlış olan kullanımlara karşı korumak için API'nizi aşırı karmaşıklaştırmanız gerektiğini düşünmüyorum. –