Domanda

Così sto lavorando sul mio DI / CIO Container OpenNETCF.IoC e ho una (ragionevole ) richiesta di funzionalità per aggiungere una qualche forma di gestione del ciclo di vita per gli oggetti IDisposable nelle collezioni del contenitore.

Il mio pensiero attuale è che, dato che non posso interrogare un oggetto per vedere se è stato smaltito, e non posso ottenere un evento per quando è stato smaltito, che devo creare una qualche forma di wrapper per oggetti che uno sviluppatore vuole che il quadro per la gestione.

In questo momento gli oggetti possono essere aggiunti con AddNew (per semplicità si suppone c'è solo un sovraccarico e non c'è alcun Add):

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

Quello che sto considerando è l'aggiunta di un nuovo metodo (beh gruppo di loro, ma si ottiene l'immagine):

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

Quando la DisposableWrappedObject assomiglia a questo:

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

Ora, quando un elementi viene aggiunto al contenitore tramite AddNewDIsposable, si aggiunge anche un EventHandler in modo che quando si ottiene Disposta (tramite l'involucro) il quadro rimuove dalla collezione sottostante.

Io in realtà ho questo implementato ed è superato i test di unità, ma sto cercando opinioni su cui questo potrebbe essere rotto, o come potrebbe essere reso più "amichevole" per lo sviluppatore che consumano.

Modifica 1

Dato che c'era una domanda su come viene utilizzato l'evento Smaltimento, ecco qualche codice (tagliato a ciò che è importante):

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);
}
È stato utile?

Soluzione

Forse mi manca qualcosa, ma perché aggiungere nuovi metodi alle API? Quando un oggetto viene aggiunto al contenitore, come si potrebbe pressofuso per verificare se è IDisposable e gestirlo in modo appropriato in caso affermativo.

Sono anche chiedendo se è necessario il distruttore. Presumendo che il contenitore è IDisposable (come l'Unità di), si può solo implementare il Basic Smaltire modello e risparmiare un sacco di GC in testa.

Alcune domande che possono essere applicabili:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top