2016-06-29 1 views
6

Disons que j'ai défini une classe MyDisposable : IDisposable. Je sais que je peux fournir une liste codée en dur de IDisposable objets à la déclaration using:Existe-t-il un moyen d'avoir une instruction using avec des cibles créées dynamiquement?

using (MyDisposable firstDisposable = new MyDisposable(), 
    secondDisposable = new MyDisposable()) 
{ 
    // do something 
} 

Maintenant, nous allons dire que j'ai quelques méthodes qui effectuent des opérations sur une collection de mes objets jetables, et je veux faire à l'intérieur d'une instruction using. Il pourrait ressembler à ceci (mais cela ne fonctionne pas bien sûr parce que le bloc à l'aide attend un ou plusieurs objets IDisposable et je passe un seul objet de collection):

using (var myDisposables = GetMyDisposables()) 
{ 
    foreach (var myDisposable in myDisposables) 
    { 
     DoSomething(myDisposable); 
     DoSomethingElse(myDisposable); 
    } 
} 

Voici les autres méthodes, juste pour la clarté :

static List<MyDisposable> GetMyDisposables() 
{ 
    throw new NotImplementedException(); // return a list of MyDisposable objects 
} 

static void DoSomething(MyDisposable withMyDisposable) 
{ 
    // something 
} 

static void DoSomethingElse(MyDisposable withMyDisposable) 
{ 
    // something else 
} 

Est-il possible que je peux y arriver avec la déclaration using? Ou dois-je simplement jeter la déclaration et la jeter manuellement?

+6

Vous pouvez créer un 'DisposableCollection : IDisposable, IEnumerable où T: IDisposable' – Lee

+0

Vous pouvez écrire 'IDisposable' qui encapsule une collection de vos objets' MyDisposable' et élimine tous ses éléments lorsque vous Disposez-le. –

+0

Pourquoi ne pas ajouter votre instruction using dans le bloc foreach? – peinearydevelopment

Répondre

7

Une approche que vous pouvez prendre est de faire une collection de IDisposable objets, ce qui est également IDisposable:

class CollectionOfDisposable<T> : IDisposable where T : IDisposable { 
    public IList<T> Members {get; private set;} 
    public CollectionOfDisposable(IEnumerable<T> members) { 
     Members = members.ToList(); 
    } 
    public void Dispose() { 
     var exceptions = new List<Exception>(); 
     foreach (var item in Members) { 
      try { 
       item.Dispose(); 
      } catch (Exception e) { 
       exceptions.Add(e); 
      } 
     } 
     if (exceptions.Count != 0) { 
      throw new AggregateException(exceptions); 
     } 
    } 
} 

Maintenant, vous pouvez écrire ceci:

using (var myDisposables = GetMyDisposables()) { 
    foreach (var myDisposable in myDisposables.Members) { 
     DoSomething(myDisposable); 
     DoSomethingElse(myDisposable); 
    } 
} 

static CollectionOfDisposable<MyDisposable> GetMyDisposables() { 
    throw new NotImplementedException(); // return a list of MyDisposable objects 
} 
+0

Pouvons-nous tous convenir que cette classe devrait exister dans la FCL? Je ne peux pas trouver quelque chose comme ça. Eh bien, en fait, j'ai trouvé ce ['System.Reactive.Disposables.CompositeDisposable'] (https://msdn.microsoft.com/en-us/library/system.reactive.disposables.compositedisposable (v = vs.103). aspx) mais il nécessite ces [extensions réactives] (https://msdn.microsoft.com/en-us/library/hh242985 (v = vs.103) .aspx). –

3

Vous devrez créer votre propre type qui implémente IDisposable et accepte une collection d'objets jetables dans son constructeur, les retenant et les jetant tous quand ils sont jetés.