Browse Source

Reimplementing interop collections using common generic parent class

See the comments at ReadOnlyInteropCollection for details

Source commit: 287505b335e182881bd45cb256139c9273758566
Martin Prikryl 2 năm trước cách đây
mục cha
commit
6f38e242d9

+ 0 - 95
dotnet/internal/ReadOnlyInteropCollectionHelper.cs

@@ -1,95 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace WinSCP
-{
-    internal class ReadOnlyInteropCollectionHelper<T> : ICollection<T>
-    {
-        public void InternalAdd(T item)
-        {
-            _list.Add(item);
-        }
-
-        public void InternalRemoveFirst()
-        {
-            _list.RemoveAt(0);
-        }
-
-        public T this[int index]
-        {
-            get
-            {
-                return _list[index];
-            }
-            set
-            {
-                throw CreateReadOnlyException();
-            }
-        }
-
-        #region ICollection<T> Members
-
-        public void Add(T item)
-        {
-            throw CreateReadOnlyException();
-        }
-
-        public void Clear()
-        {
-            throw CreateReadOnlyException();
-        }
-
-        public bool Contains(T item)
-        {
-            return _list.Contains(item);
-        }
-
-        public void CopyTo(T[] array, int arrayIndex)
-        {
-            _list.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _list.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return true; }
-        }
-
-        public bool Remove(T item)
-        {
-            throw CreateReadOnlyException();
-        }
-
-        #endregion
-
-        #region IEnumerable<T> Members
-
-        public IEnumerator<T> GetEnumerator()
-        {
-            return _list.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _list.GetEnumerator();
-        }
-
-        #endregion
-
-        private static Exception CreateReadOnlyException()
-        {
-            return new InvalidOperationException("Collection is read-only.");
-        }
-
-        private readonly List<T> _list = new List<T>();
-    }
-}

+ 2 - 82
dotnet/interopcollections/ComparisonDifferenceCollection.cs

@@ -1,5 +1,4 @@
 using System.Collections;
 using System.Collections;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace WinSCP
 namespace WinSCP
@@ -7,87 +6,8 @@ namespace WinSCP
     [Guid("28957CC8-DEBC-48D0-841B-48AD3CB3B49F")]
     [Guid("28957CC8-DEBC-48D0-841B-48AD3CB3B49F")]
     [ClassInterface(Constants.ClassInterface)]
     [ClassInterface(Constants.ClassInterface)]
     [ComVisible(true)]
     [ComVisible(true)]
-    [ComDefaultInterface(typeof(IEnumerable))]
-    public class ComparisonDifferenceCollection : ICollection<ComparisonDifference>
+    [ComDefaultInterface(typeof(IEnumerable))] // See the comment at ReadOnlyInteropCollection
+    public class ComparisonDifferenceCollection : ReadOnlyInteropCollection<ComparisonDifference>
     {
     {
-        internal ComparisonDifferenceCollection()
-        {
-        }
-
-        public ComparisonDifference this[int index]
-        {
-            get
-            {
-                return _helper[index];
-            }
-            set
-            {
-                _helper[index] = value;
-            }
-        }
-
-        #region ICollection<ComparisonDifference> Members
-
-        public void Add(ComparisonDifference item)
-        {
-            _helper.Add(item);
-        }
-
-        public void Clear()
-        {
-            _helper.Clear();
-        }
-
-        public bool Contains(ComparisonDifference item)
-        {
-            return _helper.Contains(item);
-        }
-
-        public void CopyTo(ComparisonDifference[] array, int arrayIndex)
-        {
-            _helper.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _helper.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return _helper.IsReadOnly; }
-        }
-
-        public bool Remove(ComparisonDifference item)
-        {
-            return _helper.Remove(item);
-        }
-
-        #endregion
-
-        #region IEnumerable<ComparisonDifference> Members
-
-        public IEnumerator<ComparisonDifference> GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        internal void InternalAdd(ComparisonDifference item)
-        {
-            _helper.InternalAdd(item);
-        }
-
-        private readonly ReadOnlyInteropCollectionHelper<ComparisonDifference> _helper = new ReadOnlyInteropCollectionHelper<ComparisonDifference>();
     }
     }
 }
 }

+ 76 - 0
dotnet/interopcollections/ReadOnlyInteropCollection.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace WinSCP
+{
+    // Originally, the interop classes were each implemented separatelly. Probably because at the time they were
+    // originally implemented, it was not possible to implement them via generic parent class.
+    // Now it seems to work (something was improved in in .NET interop meanwhile?)
+    //
+    // Before reimplementing using this common parent class, the actual collection classes had to have ComDefaultInterface attribute.
+    // Now it is not needed for some reason. Possibly the implicit default interface is picked rather randomly.
+    // So we still keep the attribute, just in case.
+    public class ReadOnlyInteropCollection<T> : ICollection<T>
+    {
+        internal ReadOnlyInteropCollection()
+        {
+        }
+
+        public T this[int index]
+        {
+            get => _list[index];
+            set => throw CreateReadOnlyException();
+        }
+
+        #region ICollection<T> Members
+
+        public void Add(T item) => throw CreateReadOnlyException();
+
+        public void Clear() => throw CreateReadOnlyException();
+
+        public bool Contains(T item) => _list.Contains(item);
+
+        public void CopyTo(T[] array, int arrayIndex)
+        {
+            _list.CopyTo(array, arrayIndex);
+        }
+
+        public int Count => _list.Count;
+
+        public bool IsReadOnly => true;
+
+        public bool Remove(T item)
+        {
+            throw CreateReadOnlyException();
+        }
+
+        #endregion
+
+        #region IEnumerable<T> Members
+
+        public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
+
+        #endregion
+
+        #region IEnumerable Members
+
+        IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
+
+        #endregion
+
+        internal void InternalAdd(T item)
+        {
+            _list.Add(item);
+        }
+
+        internal void InternalRemoveFirst()
+        {
+            _list.RemoveAt(0);
+        }
+
+        private static Exception CreateReadOnlyException() => new InvalidOperationException("Collection is read-only.");
+
+        private readonly List<T> _list = new List<T>();
+    }
+}

+ 2 - 82
dotnet/interopcollections/RemoteFileInfoCollection.cs

@@ -1,5 +1,4 @@
 using System.Collections;
 using System.Collections;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace WinSCP
 namespace WinSCP
@@ -7,87 +6,8 @@ namespace WinSCP
     [Guid("39AA3D00-578C-49AF-B3E4-16CE26C710C6")]
     [Guid("39AA3D00-578C-49AF-B3E4-16CE26C710C6")]
     [ClassInterface(Constants.ClassInterface)]
     [ClassInterface(Constants.ClassInterface)]
     [ComVisible(true)]
     [ComVisible(true)]
-    [ComDefaultInterface(typeof(IEnumerable))]
-    public class RemoteFileInfoCollection : ICollection<RemoteFileInfo>
+    [ComDefaultInterface(typeof(IEnumerable))] // See the comment at ReadOnlyInteropCollection
+    public class RemoteFileInfoCollection : ReadOnlyInteropCollection<RemoteFileInfo>
     {
     {
-        internal RemoteFileInfoCollection()
-        {
-        }
-
-        public RemoteFileInfo this[int index]
-        {
-            get
-            {
-                return _helper[index];
-            }
-            set
-            {
-                _helper[index] = value;
-            }
-        }
-
-        #region ICollection<RemoteFileInfo> Members
-
-        public void Add(RemoteFileInfo item)
-        {
-            _helper.Add(item);
-        }
-
-        public void Clear()
-        {
-            _helper.Clear();
-        }
-
-        public bool Contains(RemoteFileInfo item)
-        {
-            return _helper.Contains(item);
-        }
-
-        public void CopyTo(RemoteFileInfo[] array, int arrayIndex)
-        {
-            _helper.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _helper.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return _helper.IsReadOnly; }
-        }
-
-        public bool Remove(RemoteFileInfo item)
-        {
-            return _helper.Remove(item);
-        }
-
-        #endregion
-
-        #region IEnumerable<RemoteFileInfo> Members
-
-        public IEnumerator<RemoteFileInfo> GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        internal void InternalAdd(RemoteFileInfo item)
-        {
-            _helper.InternalAdd(item);
-        }
-
-        private readonly ReadOnlyInteropCollectionHelper<RemoteFileInfo> _helper = new ReadOnlyInteropCollectionHelper<RemoteFileInfo>();
     }
     }
 }
 }

+ 2 - 82
dotnet/interopcollections/RemovalEventArgsCollection.cs

@@ -1,5 +1,4 @@
 using System.Collections;
 using System.Collections;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace WinSCP
 namespace WinSCP
@@ -7,87 +6,8 @@ namespace WinSCP
     [Guid("574FF430-FD40-41F9-9A04-971D3CF844B7")]
     [Guid("574FF430-FD40-41F9-9A04-971D3CF844B7")]
     [ClassInterface(Constants.ClassInterface)]
     [ClassInterface(Constants.ClassInterface)]
     [ComVisible(true)]
     [ComVisible(true)]
-    [ComDefaultInterface(typeof(IEnumerable))]
-    public class RemovalEventArgsCollection : ICollection<RemovalEventArgs>
+    [ComDefaultInterface(typeof(IEnumerable))] // See the comment at ReadOnlyInteropCollection
+    public class RemovalEventArgsCollection : ReadOnlyInteropCollection<RemovalEventArgs>
     {
     {
-        internal RemovalEventArgsCollection()
-        {
-        }
-
-        public RemovalEventArgs this[int index]
-        {
-            get
-            {
-                return _helper[index];
-            }
-            set
-            {
-                _helper[index] = value;
-            }
-        }
-
-        #region ICollection<RemovalEventArgs> Members
-
-        public void Add(RemovalEventArgs item)
-        {
-            _helper.Add(item);
-        }
-
-        public void Clear()
-        {
-            _helper.Clear();
-        }
-
-        public bool Contains(RemovalEventArgs item)
-        {
-            return _helper.Contains(item);
-        }
-
-        public void CopyTo(RemovalEventArgs[] array, int arrayIndex)
-        {
-            _helper.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _helper.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return _helper.IsReadOnly; }
-        }
-
-        public bool Remove(RemovalEventArgs item)
-        {
-            return _helper.Remove(item);
-        }
-
-        #endregion
-
-        #region IEnumerable<RemovalEventArgs> Members
-
-        public IEnumerator<RemovalEventArgs> GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        internal void InternalAdd(RemovalEventArgs item)
-        {
-            _helper.InternalAdd(item);
-        }
-
-        private readonly ReadOnlyInteropCollectionHelper<RemovalEventArgs> _helper = new ReadOnlyInteropCollectionHelper<RemovalEventArgs>();
     }
     }
 }
 }

+ 2 - 82
dotnet/interopcollections/SessionRemoteExceptionCollection.cs

@@ -1,5 +1,4 @@
 using System.Collections;
 using System.Collections;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace WinSCP
 namespace WinSCP
@@ -7,87 +6,8 @@ namespace WinSCP
     [Guid("2309282F-B89B-4F6B-AEB1-D3E1629B7033")]
     [Guid("2309282F-B89B-4F6B-AEB1-D3E1629B7033")]
     [ClassInterface(Constants.ClassInterface)]
     [ClassInterface(Constants.ClassInterface)]
     [ComVisible(true)]
     [ComVisible(true)]
-    [ComDefaultInterface(typeof(IEnumerable))]
-    public class SessionRemoteExceptionCollection : ICollection<SessionRemoteException>
+    [ComDefaultInterface(typeof(IEnumerable))] // See the comment at ReadOnlyInteropCollection
+    public class SessionRemoteExceptionCollection : ReadOnlyInteropCollection<SessionRemoteException>
     {
     {
-        internal SessionRemoteExceptionCollection()
-        {
-        }
-
-        public SessionRemoteException this[int index]
-        {
-            get
-            {
-                return _helper[index];
-            }
-            set
-            {
-                _helper[index] = value;
-            }
-        }
-
-        #region ICollection<SessionRemoteException> Members
-
-        public void Add(SessionRemoteException item)
-        {
-            _helper.Add(item);
-        }
-
-        public void Clear()
-        {
-            _helper.Clear();
-        }
-
-        public bool Contains(SessionRemoteException item)
-        {
-            return _helper.Contains(item);
-        }
-
-        public void CopyTo(SessionRemoteException[] array, int arrayIndex)
-        {
-            _helper.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _helper.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return _helper.IsReadOnly; }
-        }
-
-        public bool Remove(SessionRemoteException item)
-        {
-            return _helper.Remove(item);
-        }
-
-        #endregion
-
-        #region IEnumerable<SessionRemoteException> Members
-
-        public IEnumerator<SessionRemoteException> GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        internal void InternalAdd(SessionRemoteException item)
-        {
-            _helper.InternalAdd(item);
-        }
-
-        private readonly ReadOnlyInteropCollectionHelper<SessionRemoteException> _helper = new ReadOnlyInteropCollectionHelper<SessionRemoteException>();
     }
     }
 }
 }

+ 2 - 87
dotnet/interopcollections/StringCollection.cs

@@ -1,5 +1,4 @@
 using System.Collections;
 using System.Collections;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace WinSCP
 namespace WinSCP
@@ -7,92 +6,8 @@ namespace WinSCP
     [Guid("E402CB1F-6219-4C79-9EDF-1914D9589909")]
     [Guid("E402CB1F-6219-4C79-9EDF-1914D9589909")]
     [ClassInterface(Constants.ClassInterface)]
     [ClassInterface(Constants.ClassInterface)]
     [ComVisible(true)]
     [ComVisible(true)]
-    [ComDefaultInterface(typeof(IEnumerable))]
-    public class StringCollection : ICollection<string>
+    [ComDefaultInterface(typeof(IEnumerable))] // See the comment at ReadOnlyInteropCollection
+    public class StringCollection : ReadOnlyInteropCollection<string>
     {
     {
-        internal StringCollection()
-        {
-        }
-
-        public string this[int index]
-        {
-            get
-            {
-                return _helper[index];
-            }
-            set
-            {
-                _helper[index] = value;
-            }
-        }
-
-        #region ICollection<string> Members
-
-        public void Add(string item)
-        {
-            _helper.Add(item);
-        }
-
-        public void Clear()
-        {
-            _helper.Clear();
-        }
-
-        public bool Contains(string item)
-        {
-            return _helper.Contains(item);
-        }
-
-        public void CopyTo(string[] array, int arrayIndex)
-        {
-            _helper.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _helper.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return _helper.IsReadOnly; }
-        }
-
-        public bool Remove(string item)
-        {
-            return _helper.Remove(item);
-        }
-
-        #endregion
-
-        #region IEnumerable<SessionRemoteException> Members
-
-        public IEnumerator<string> GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        internal void InternalAdd(string item)
-        {
-            _helper.InternalAdd(item);
-        }
-
-        internal void InternalRemoveFirst()
-        {
-            _helper.InternalRemoveFirst();
-        }
-
-        private readonly ReadOnlyInteropCollectionHelper<string> _helper = new ReadOnlyInteropCollectionHelper<string>();
     }
     }
 }
 }

+ 2 - 82
dotnet/interopcollections/TransferEventArgsCollection.cs

@@ -1,5 +1,4 @@
 using System.Collections;
 using System.Collections;
-using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 
 
 namespace WinSCP
 namespace WinSCP
@@ -7,87 +6,8 @@ namespace WinSCP
     [Guid("0285917B-581A-4F6F-9A9D-1C34ABFB4E38")]
     [Guid("0285917B-581A-4F6F-9A9D-1C34ABFB4E38")]
     [ClassInterface(Constants.ClassInterface)]
     [ClassInterface(Constants.ClassInterface)]
     [ComVisible(true)]
     [ComVisible(true)]
-    [ComDefaultInterface(typeof(IEnumerable))]
-    public class TransferEventArgsCollection : ICollection<TransferEventArgs>
+    [ComDefaultInterface(typeof(IEnumerable))] // See the comment at ReadOnlyInteropCollection
+    public class TransferEventArgsCollection : ReadOnlyInteropCollection<TransferEventArgs>
     {
     {
-        internal TransferEventArgsCollection()
-        {
-        }
-
-        public TransferEventArgs this[int index]
-        {
-            get
-            {
-                return _helper[index];
-            }
-            set
-            {
-                _helper[index] = value;
-            }
-        }
-
-        #region ICollection<TransferEventArgs> Members
-
-        public void Add(TransferEventArgs item)
-        {
-            _helper.Add(item);
-        }
-
-        public void Clear()
-        {
-            _helper.Clear();
-        }
-
-        public bool Contains(TransferEventArgs item)
-        {
-            return _helper.Contains(item);
-        }
-
-        public void CopyTo(TransferEventArgs[] array, int arrayIndex)
-        {
-            _helper.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return _helper.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return _helper.IsReadOnly; }
-        }
-
-        public bool Remove(TransferEventArgs item)
-        {
-            return _helper.Remove(item);
-        }
-
-        #endregion
-
-        #region IEnumerable<SessionRemoteException> Members
-
-        public IEnumerator<TransferEventArgs> GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        #region IEnumerable Members
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _helper.GetEnumerator();
-        }
-
-        #endregion
-
-        internal void InternalAdd(TransferEventArgs item)
-        {
-            _helper.InternalAdd(item);
-        }
-
-        private readonly ReadOnlyInteropCollectionHelper<TransferEventArgs> _helper = new ReadOnlyInteropCollectionHelper<TransferEventArgs>();
     }
     }
 }
 }