Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/RM-8903-Optimize-iteration-on-ClientTransactionExtensionCollection #829

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with re-motion; if not, see http://www.gnu.org/licenses.
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
Expand Down Expand Up @@ -69,6 +70,39 @@ public void Initialization ()
Assert.That(((IClientTransactionExtension)collection).Key, Is.EqualTo("abc"));
}

[Test]
public void GetEnumerator_IEnumerableGeneric ()
{
_collection.Add(_extension1.Object);
_collection.Add(_extension2.Object);

using IEnumerator<IClientTransactionExtension> enumerator = ((IEnumerable<IClientTransactionExtension>)_collection).GetEnumerator();

Assert.That(enumerator.Current, Is.Null);
Assert.That(enumerator.MoveNext(), Is.True);
Assert.That(enumerator.Current, Is.EqualTo(_extension1.Object));
Assert.That(enumerator.MoveNext(), Is.True);
Assert.That(enumerator.Current, Is.EqualTo(_extension2.Object));
Assert.That(enumerator.MoveNext(), Is.False);
}

[Test]
public void GetEnumerator_ForIEnumerable ()
{
_collection.Add(_extension1.Object);
_collection.Add(_extension2.Object);

// ReSharper disable once NotDisposedResource
IEnumerator enumerator = ((IEnumerable)_collection).GetEnumerator();

Assert.That(enumerator.Current, Is.Null);
Assert.That(enumerator.MoveNext(), Is.True);
Assert.That(enumerator.Current, Is.EqualTo(_extension1.Object));
Assert.That(enumerator.MoveNext(), Is.True);
Assert.That(enumerator.Current, Is.EqualTo(_extension2.Object));
Assert.That(enumerator.MoveNext(), Is.False);
}

[Test]
public void Add ()
{
Expand All @@ -95,10 +129,11 @@ public void Insert ()
[Test]
public void Remove ()
{
_collection.Add(_extension2.Object);
_collection.Add(_extension1.Object);
Assert.That(_collection.Count, Is.EqualTo(1));
Assert.That(_collection.Count, Is.EqualTo(2));
_collection.Remove(_extension1.Object.Key);
Assert.That(_collection.Count, Is.EqualTo(0));
Assert.That(_collection.Count, Is.EqualTo(1));
_collection.Remove(_extension1.Object.Key);
//expectation: no exception
}
Expand All @@ -113,12 +148,13 @@ public void Indexer ()
}

[Test]
public void IndexerWithName ()
public void IndexerWithKey ()
{
_collection.Add(_extension1.Object);
_collection.Add(_extension2.Object);
Assert.That(_collection[_extension1.Object.Key], Is.SameAs(_extension1.Object));
Assert.That(_collection[_extension2.Object.Key], Is.SameAs(_extension2.Object));
Assert.That(_collection["unknown"], Is.Null);
}

[Test]
Expand All @@ -144,7 +180,7 @@ public void AddWithDuplicateKey ()
}

[Test]
public void InsertWithDuplicateName ()
public void InsertWithDuplicateKey ()
{
_collection.Insert(0, _extension1.Object);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with re-motion; if not, see http://www.gnu.org/licenses.
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
Expand All @@ -30,9 +31,10 @@ namespace Remotion.Data.DomainObjects
/// A collection of <see cref="IClientTransactionExtension"/>s.
/// </summary>
[Serializable]
public class ClientTransactionExtensionCollection : CommonCollection, IClientTransactionExtension
public class ClientTransactionExtensionCollection : IClientTransactionExtension, IReadOnlyList<IClientTransactionExtension>
{
private readonly string _key;
private readonly List<KeyValuePair<string, IClientTransactionExtension>> _extensions = new();

public ClientTransactionExtensionCollection (string key)
{
Expand All @@ -53,7 +55,7 @@ public IClientTransactionExtension? this[string key]
{
ArgumentUtility.CheckNotNullOrEmpty("key", key);

return (IClientTransactionExtension?)BaseGetObject(key);
return _extensions.FirstOrDefault(e => KeyPredicate(e, key)).Value;
}
}

Expand All @@ -64,7 +66,7 @@ public IClientTransactionExtension? this[string key]
/// <returns>The <see cref="IClientTransactionExtension"/> of the given <paramref name="index"/>.</returns>
public IClientTransactionExtension this[int index]
{
get { return (IClientTransactionExtension)BaseGetObject(index); }
get { return _extensions[index].Value; }
}

string IClientTransactionExtension.Key
Expand All @@ -86,10 +88,10 @@ public void Add (IClientTransactionExtension clientTransactionExtension)
var key = clientTransactionExtension.Key;
Assertion.IsNotNull(key, "IClientTransactionExtension.Key must not return null");

if (BaseContainsKey(key))
if (_extensions.Any(e => KeyPredicate(e, key)))
throw new InvalidOperationException(string.Format("An extension with key '{0}' is already part of the collection.", key));

BaseAdd(key, clientTransactionExtension);
_extensions.Add(new KeyValuePair<string, IClientTransactionExtension>(key, clientTransactionExtension));
}

/// <summary>
Expand All @@ -100,7 +102,7 @@ public void Remove (string key)
{
ArgumentUtility.CheckNotNullOrEmpty("key", key);

BaseRemove(key);
_extensions.RemoveAll(e => KeyPredicate(e, key));
}

/// <summary>
Expand All @@ -112,7 +114,7 @@ public int IndexOf (string key)
{
ArgumentUtility.CheckNotNullOrEmpty("key", key);

return BaseIndexOfKey(key);
return _extensions.FindIndex(e => KeyPredicate(e, key));
}

/// <summary>
Expand All @@ -130,12 +132,20 @@ public void Insert (int index, IClientTransactionExtension clientTransactionExte
var key = clientTransactionExtension.Key;
Assertion.IsNotNull(key, "IClientTransactionExtension.Key must not return null");

if (BaseContainsKey(key))
if (_extensions.Any(e => KeyPredicate(e, key)))
throw new InvalidOperationException(string.Format("An extension with key '{0}' is already part of the collection.", key));

BaseInsert(index, key, clientTransactionExtension);
_extensions.Insert(index, new KeyValuePair<string, IClientTransactionExtension>(key, clientTransactionExtension));
}

IEnumerator<IClientTransactionExtension> IEnumerable<IClientTransactionExtension>.GetEnumerator () => _extensions.Select(e => e.Value).GetEnumerator();

IEnumerator IEnumerable.GetEnumerator () => ((IEnumerable<IClientTransactionExtension>)this).GetEnumerator();

public int Count => _extensions.Count;

private static bool KeyPredicate (KeyValuePair<string, IClientTransactionExtension> extension, string key) => string.Equals(extension.Key, key, StringComparison.Ordinal);

#region Notification methods

[EditorBrowsable(EditorBrowsableState.Never)]
Expand Down Expand Up @@ -212,6 +222,7 @@ public void ObjectsLoaded (ClientTransaction clientTransaction, IReadOnlyList<Do
this[i].ObjectsLoaded(clientTransaction, loadedDomainObjects);
}

[EditorBrowsable(EditorBrowsableState.Never)]
public void ObjectsUnloading (ClientTransaction clientTransaction, IReadOnlyList<DomainObject> unloadedDomainObjects)
{
ArgumentUtility.DebugCheckNotNull("unloadedDomainObjects", unloadedDomainObjects);
Expand All @@ -220,6 +231,7 @@ public void ObjectsUnloading (ClientTransaction clientTransaction, IReadOnlyList
this[i].ObjectsUnloading(clientTransaction, unloadedDomainObjects);
}

[EditorBrowsable(EditorBrowsableState.Never)]
public void ObjectsUnloaded (ClientTransaction clientTransaction, IReadOnlyList<DomainObject> unloadedDomainObjects)
{
ArgumentUtility.DebugCheckNotNull("unloadedDomainObjects", unloadedDomainObjects);
Expand Down