From c1e04db575a4427cb286b43717ffafd378aa879c Mon Sep 17 00:00:00 2001 From: Marcell Toth Date: Sun, 15 Dec 2019 14:41:23 +0100 Subject: [PATCH 1/4] Add test that demonstrates how the collections don't currently implement IReadOnlyCollection --- .../PersistentCollectionsFixture.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/NHibernate.Test/CollectionTest/PersistentCollectionsFixture.cs b/src/NHibernate.Test/CollectionTest/PersistentCollectionsFixture.cs index 5a7f9679773..03439d8a47a 100644 --- a/src/NHibernate.Test/CollectionTest/PersistentCollectionsFixture.cs +++ b/src/NHibernate.Test/CollectionTest/PersistentCollectionsFixture.cs @@ -36,5 +36,22 @@ public void AddRangeWorksCorrectly() Assert.That(items, Is.EqualTo(new[] {"A", "B", "C", "D", "E"})); } + + [Test] + public void SelectManyWorksCorrectlyWithIReadOnlyCollection() + { + var bags = new IReadOnlyCollection[] + { + new List {"A"}, + new PersistentGenericBag(null, new[] {"B"}), + new PersistentIdentifierBag(null, new[] {"C"}), + (IReadOnlyList)new PersistentGenericList(null, new[] {"D"}), + new PersistentGenericSet(null, new HashSet {"E"}) + }; + + var items = bags.SelectMany(b => b).ToArray(); + + Assert.That(items, Is.EqualTo(new[] {"A", "B", "C", "D", "E"})); + } } } From 053cd5ae0beb092ec12f28bfecf21c0512797a6f Mon Sep 17 00:00:00 2001 From: Marcell Toth Date: Sun, 15 Dec 2019 15:01:40 +0100 Subject: [PATCH 2/4] Make persistent collection classes implement the IReadOnly* interfaces --- .../Collection/Generic/PersistentGenericBag.cs | 2 +- .../Generic/PersistentGenericIdentifierBag.cs | 2 +- .../Collection/Generic/PersistentGenericList.cs | 2 +- .../Collection/Generic/PersistentGenericMap.cs | 13 ++++++++++++- .../Collection/Generic/PersistentGenericSet.cs | 2 +- .../Collection/Generic/SetHelpers/ISetSnapshot.cs | 4 ++-- .../Collection/Generic/SetHelpers/SetSnapShot.cs | 7 ++++++- 7 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/NHibernate/Collection/Generic/PersistentGenericBag.cs b/src/NHibernate/Collection/Generic/PersistentGenericBag.cs index d58be9c9a94..c8bd0e86793 100644 --- a/src/NHibernate/Collection/Generic/PersistentGenericBag.cs +++ b/src/NHibernate/Collection/Generic/PersistentGenericBag.cs @@ -25,7 +25,7 @@ namespace NHibernate.Collection.Generic /// The underlying collection used is an [Serializable] [DebuggerTypeProxy(typeof (CollectionProxy<>))] - public partial class PersistentGenericBag : AbstractPersistentCollection, IList, IList, IQueryable + public partial class PersistentGenericBag : AbstractPersistentCollection, IList, IReadOnlyList, IList, IQueryable { // TODO NH: find a way to writeonce (no duplicated code from PersistentBag) diff --git a/src/NHibernate/Collection/Generic/PersistentGenericIdentifierBag.cs b/src/NHibernate/Collection/Generic/PersistentGenericIdentifierBag.cs index b7b23ca80a6..884d454b76e 100644 --- a/src/NHibernate/Collection/Generic/PersistentGenericIdentifierBag.cs +++ b/src/NHibernate/Collection/Generic/PersistentGenericIdentifierBag.cs @@ -33,7 +33,7 @@ namespace NHibernate.Collection.Generic /// [Serializable] [DebuggerTypeProxy(typeof (CollectionProxy<>))] - public partial class PersistentIdentifierBag : AbstractPersistentCollection, IList, IList, IQueryable + public partial class PersistentIdentifierBag : AbstractPersistentCollection, IList, IReadOnlyList, IList, IQueryable { /* NH considerations: * For various reason we know that the underlining type will be a List or a diff --git a/src/NHibernate/Collection/Generic/PersistentGenericList.cs b/src/NHibernate/Collection/Generic/PersistentGenericList.cs index 4e54262a85e..bf8082395f1 100644 --- a/src/NHibernate/Collection/Generic/PersistentGenericList.cs +++ b/src/NHibernate/Collection/Generic/PersistentGenericList.cs @@ -22,7 +22,7 @@ namespace NHibernate.Collection.Generic /// The underlying collection used is a [Serializable] [DebuggerTypeProxy(typeof (CollectionProxy<>))] - public partial class PersistentGenericList : AbstractPersistentCollection, IList, IList, IQueryable + public partial class PersistentGenericList : AbstractPersistentCollection, IList, IReadOnlyList, IList, IQueryable { protected IList WrappedList; diff --git a/src/NHibernate/Collection/Generic/PersistentGenericMap.cs b/src/NHibernate/Collection/Generic/PersistentGenericMap.cs index 20f4d5ba657..d61b1a68d43 100644 --- a/src/NHibernate/Collection/Generic/PersistentGenericMap.cs +++ b/src/NHibernate/Collection/Generic/PersistentGenericMap.cs @@ -23,7 +23,7 @@ namespace NHibernate.Collection.Generic /// The type of the elements in the IDictionary. [Serializable] [DebuggerTypeProxy(typeof(DictionaryProxy<,>))] - public partial class PersistentGenericMap : AbstractPersistentCollection, IDictionary, ICollection + public partial class PersistentGenericMap : AbstractPersistentCollection, IDictionary, IReadOnlyDictionary, ICollection { protected IDictionary WrappedMap; private readonly ICollection _wrappedValues; @@ -360,6 +360,17 @@ public ICollection Values } } + IEnumerable IReadOnlyDictionary.Keys + { + get { return Keys; } + } + + IEnumerable IReadOnlyDictionary.Values + { + get { return Values; } + } + + #endregion #region ICollection> Members diff --git a/src/NHibernate/Collection/Generic/PersistentGenericSet.cs b/src/NHibernate/Collection/Generic/PersistentGenericSet.cs index 16a6169ce0c..03a273cd32e 100644 --- a/src/NHibernate/Collection/Generic/PersistentGenericSet.cs +++ b/src/NHibernate/Collection/Generic/PersistentGenericSet.cs @@ -21,7 +21,7 @@ namespace NHibernate.Collection.Generic /// [Serializable] [DebuggerTypeProxy(typeof(CollectionProxy<>))] - public partial class PersistentGenericSet : AbstractPersistentCollection, ISet, IQueryable + public partial class PersistentGenericSet : AbstractPersistentCollection, ISet, IReadOnlyCollection, IQueryable { /// /// The that NHibernate is wrapping. diff --git a/src/NHibernate/Collection/Generic/SetHelpers/ISetSnapshot.cs b/src/NHibernate/Collection/Generic/SetHelpers/ISetSnapshot.cs index 3b86f42f41a..20f9983911f 100644 --- a/src/NHibernate/Collection/Generic/SetHelpers/ISetSnapshot.cs +++ b/src/NHibernate/Collection/Generic/SetHelpers/ISetSnapshot.cs @@ -3,8 +3,8 @@ namespace NHibernate.Collection.Generic.SetHelpers { - internal interface ISetSnapshot : ICollection, ICollection + internal interface ISetSnapshot : ICollection, IReadOnlyCollection, ICollection { bool TryGetValue(T element, out T value); } -} \ No newline at end of file +} diff --git a/src/NHibernate/Collection/Generic/SetHelpers/SetSnapShot.cs b/src/NHibernate/Collection/Generic/SetHelpers/SetSnapShot.cs index 70492c45532..143d7f2564d 100644 --- a/src/NHibernate/Collection/Generic/SetHelpers/SetSnapShot.cs +++ b/src/NHibernate/Collection/Generic/SetHelpers/SetSnapShot.cs @@ -83,6 +83,11 @@ int ICollection.Count get { return _elements.Count; } } + int IReadOnlyCollection.Count + { + get { return _elements.Count; } + } + public bool IsReadOnly { get { return ((ICollection)_elements).IsReadOnly; } @@ -101,4 +106,4 @@ public bool TryGetValue(T element, out T value) return false; } } -} \ No newline at end of file +} From 2d7df2ed6a980c014de7ece9d333ee76d433804a Mon Sep 17 00:00:00 2001 From: Marcell Toth Date: Sun, 15 Dec 2019 15:18:57 +0100 Subject: [PATCH 3/4] Fix formatting issue. Remove extra blank line from PersistentGenericMap.cs --- src/NHibernate/Collection/Generic/PersistentGenericMap.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NHibernate/Collection/Generic/PersistentGenericMap.cs b/src/NHibernate/Collection/Generic/PersistentGenericMap.cs index d61b1a68d43..6133897c80d 100644 --- a/src/NHibernate/Collection/Generic/PersistentGenericMap.cs +++ b/src/NHibernate/Collection/Generic/PersistentGenericMap.cs @@ -369,7 +369,6 @@ IEnumerable IReadOnlyDictionary.Values { get { return Values; } } - #endregion From 2b8ab7e00bd616f6495aeef0bd894bfa45b05f6e Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Mon, 16 Dec 2019 09:55:40 +1300 Subject: [PATCH 4/4] Generate Async --- src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs | 2 +- .../Async/Collection/Generic/PersistentGenericIdentifierBag.cs | 2 +- .../Async/Collection/Generic/PersistentGenericList.cs | 2 +- src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs | 2 +- src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs index ca332f273ec..de777215a65 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericBag.cs @@ -27,7 +27,7 @@ namespace NHibernate.Collection.Generic { using System.Threading.Tasks; using System.Threading; - public partial class PersistentGenericBag : AbstractPersistentCollection, IList, IList, IQueryable + public partial class PersistentGenericBag : AbstractPersistentCollection, IList, IReadOnlyList, IList, IQueryable { public override async Task DisassembleAsync(ICollectionPersister persister, CancellationToken cancellationToken) diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs index 80f8c950ec2..7250c95ad55 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericIdentifierBag.cs @@ -28,7 +28,7 @@ namespace NHibernate.Collection.Generic { using System.Threading.Tasks; using System.Threading; - public partial class PersistentIdentifierBag : AbstractPersistentCollection, IList, IList, IQueryable + public partial class PersistentIdentifierBag : AbstractPersistentCollection, IList, IReadOnlyList, IList, IQueryable { /// diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs index e6bcfa3812a..1a1fe094e62 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericList.cs @@ -27,7 +27,7 @@ namespace NHibernate.Collection.Generic { using System.Threading.Tasks; using System.Threading; - public partial class PersistentGenericList : AbstractPersistentCollection, IList, IList, IQueryable + public partial class PersistentGenericList : AbstractPersistentCollection, IList, IReadOnlyList, IList, IQueryable { //Since 5.3 diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs index 9f8d0090ea4..567046ef15e 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericMap.cs @@ -27,7 +27,7 @@ namespace NHibernate.Collection.Generic { using System.Threading.Tasks; using System.Threading; - public partial class PersistentGenericMap : AbstractPersistentCollection, IDictionary, ICollection + public partial class PersistentGenericMap : AbstractPersistentCollection, IDictionary, IReadOnlyDictionary, ICollection { //Since 5.3 diff --git a/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs b/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs index 9e5cb020340..d28409ada26 100644 --- a/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs +++ b/src/NHibernate/Async/Collection/Generic/PersistentGenericSet.cs @@ -28,7 +28,7 @@ namespace NHibernate.Collection.Generic { using System.Threading.Tasks; using System.Threading; - public partial class PersistentGenericSet : AbstractPersistentCollection, ISet, IQueryable + public partial class PersistentGenericSet : AbstractPersistentCollection, ISet, IReadOnlyCollection, IQueryable { //Since 5.3