Question

Alors, je travaille sur mon DI / IoC Container OpenNETCF.IoC et j'ai un (raisonnable ) demande de fonctionnalité pour ajouter une certaine forme de gestion du cycle de vie des produits IDisposable dans les collections de conteneurs.

Ma pensée actuelle est que, puisque je ne peux pas interroger un objet pour voir si elle a été placée, et je ne peux pas obtenir un événement quand il a été disposé, que je dois créer une certaine forme d'emballage pour les objets un développeur souhaite que le cadre de gestion.

Droit des objets peuvent maintenant être ajoutés avec AddNew (par souci de simplicité, nous supposons qu'il n'y a qu'une surcharge et il n'y a pas Ajouter):

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

Qu'est-ce que je considère est l'ajout d'une nouvelle méthode (bien groupe d'entre eux, mais vous obtenez l'image):

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

Si le DisposableWrappedObject ressemble à ceci:

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

Maintenant, quand un des éléments est ajouté au conteneur via AddNewDIsposable, un gestionnaire d'événements est également ajouté de telle sorte que quand il est vendu (par l'emballage) le cadre supprime de la collection sous-jacente.

J'ai fait cette mise en œuvre et il est passé les tests unitaires, mais je suis à la recherche d'opinions sur l'endroit où cela pourrait être cassé, ou comment il pourrait être plus « convivial » pour le développeur consommation.

EDIT 1

Comme il y avait une question sur la façon dont l'événement est utilisé Mise au rebut, voici un code (coupé à ce qui est important):

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);
}
Était-ce utile?

La solution

Peut-être que je manque quelque chose, mais pourquoi ajouter de nouvelles méthodes à l'API? Lorsqu'un objet est ajouté au conteneur, vous pourriez aussi sous pression pour vérifier si elle est IDisposable et gérer de façon appropriée le cas échéant.

Je me demande aussi si vous avez besoin destructor. En présumant le conteneur est IDisposable (comme l'unité de), vous pouvez simplement mettre en œuvre le Dispose de base Motif et économiser beaucoup de frais généraux GC.

Voici quelques questions qui peuvent être applicables:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top