From 94b941ee95a294228516097c269e27dfa41593ab Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 13 Jan 2020 09:10:13 -0800 Subject: Provide Record enumerator on View that disposes fetched Records --- src/WixToolset.Core.WindowsInstaller/Msi/View.cs | 83 ++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 4 deletions(-) (limited to 'src/WixToolset.Core.WindowsInstaller/Msi/View.cs') diff --git a/src/WixToolset.Core.WindowsInstaller/Msi/View.cs b/src/WixToolset.Core.WindowsInstaller/Msi/View.cs index 1beb72da..0fb7fc62 100644 --- a/src/WixToolset.Core.WindowsInstaller/Msi/View.cs +++ b/src/WixToolset.Core.WindowsInstaller/Msi/View.cs @@ -3,6 +3,8 @@ namespace WixToolset.Core.WindowsInstaller.Msi { using System; + using System.Collections; + using System.Collections.Generic; using System.Globalization; /// @@ -109,6 +111,11 @@ namespace WixToolset.Core.WindowsInstaller.Msi this.Handle = handle; } + /// + /// Enumerator that automatically disposes of the retrieved Records. + /// + public IEnumerable Records => new ViewEnumerable(this); + /// /// Executes a view with no customizable parameters. /// @@ -124,7 +131,7 @@ namespace WixToolset.Core.WindowsInstaller.Msi /// Record containing parameters to be substituded into the view. public void Execute(Record record) { - int error = MsiInterop.MsiViewExecute(this.Handle, null == record ? 0 : record.Handle); + var error = MsiInterop.MsiViewExecute(this.Handle, null == record ? 0 : record.Handle); if (0 != error) { throw new MsiException(error); @@ -137,9 +144,7 @@ namespace WixToolset.Core.WindowsInstaller.Msi /// Returns the fetched record; otherwise null. public Record Fetch() { - uint recordHandle; - - int error = MsiInterop.MsiViewFetch(this.Handle, out recordHandle); + var error = MsiInterop.MsiViewFetch(this.Handle, out var recordHandle); if (259 == error) { return null; @@ -183,5 +188,75 @@ namespace WixToolset.Core.WindowsInstaller.Msi return new Record(recordHandle); } + + private class ViewEnumerable : IEnumerable + { + private readonly View view; + + public ViewEnumerable(View view) => this.view = view; + + public IEnumerator GetEnumerator() => new ViewEnumerator(this.view); + + IEnumerator IEnumerable.GetEnumerator() => new ViewEnumerator(this.view); + } + + private class ViewEnumerator : IEnumerator + { + private readonly View view; + private readonly List records = new List(); + private int position = -1; + private bool disposed; + + public ViewEnumerator(View view) => this.view = view; + + public Record Current => this.records[this.position]; + + object IEnumerator.Current => this.records[this.position]; + + public bool MoveNext() + { + if (this.position + 1 >= this.records.Count) + { + var record = this.view.Fetch(); + + if (record == null) + { + return false; + } + + this.records.Add(record); + this.position = this.records.Count - 1; + } + else + { + ++this.position; + } + + return true; + } + + public void Reset() => this.position = -1; + + public void Dispose() + { + this.Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposed) + { + if (disposing) + { + foreach (var record in this.records) + { + record.Dispose(); + } + } + + this.disposed = true; + } + } + } } } -- cgit v1.2.3-55-g6feb