Skip to content

Commit

Permalink
simplify ServiceComponentList (#2566)
Browse files Browse the repository at this point in the history
  • Loading branch information
bollhals authored Mar 10, 2022
1 parent 9740247 commit 5a732c6
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 96 deletions.
13 changes: 9 additions & 4 deletions TechTalk.SpecFlow/Assist/Service.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@

namespace TechTalk.SpecFlow.Assist
{
#nullable enable
public class Service
{
public ServiceComponentList<IValueComparer> ValueComparers { get; private set; }
public ServiceComponentList<IValueRetriever> ValueRetrievers { get; private set; }

public static Service Instance { get; internal set; } = new Service();
public static Service Instance { get; } = new Service();

public Service()
{
RestoreDefaults();
ValueComparers = new SpecFlowDefaultValueComparerList();
ValueRetrievers = new SpecFlowDefaultValueRetrieverList();
}

public void RestoreDefaults()
Expand Down Expand Up @@ -45,12 +47,15 @@ public void UnregisterValueRetriever(IValueRetriever valueRetriever)
ValueRetrievers.Unregister(valueRetriever);
}

public IValueRetriever GetValueRetrieverFor(TableRow row, Type targetType, Type propertyType)
public IValueRetriever? GetValueRetrieverFor(TableRow row, Type targetType, Type propertyType)
{
var keyValuePair = new KeyValuePair<string, string>(row[0], row[1]);
foreach (var valueRetriever in ValueRetrievers)
{
if (valueRetriever.CanRetrieve(new KeyValuePair<string, string>(row[0], row[1]), targetType, propertyType))
if (valueRetriever.CanRetrieve(keyValuePair, targetType, propertyType))
{
return valueRetriever;
}
}
return null;
}
Expand Down
48 changes: 33 additions & 15 deletions TechTalk.SpecFlow/Assist/ServiceComponentList.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace TechTalk.SpecFlow.Assist
{
#nullable enable
public class ServiceComponentList<T> : IEnumerable<T>
{
private readonly List<T> components;
private T? defaultComponent;

private ValueHolder<T> defaultComponent;

private IEnumerable<T> componentsWithDefault => components.Concat(defaultComponent);

IEnumerator<T> IEnumerable<T>.GetEnumerator() => componentsWithDefault.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)componentsWithDefault).GetEnumerator();
public List<T>.Enumerator GetEnumerator() => components.GetEnumerator();
IEnumerator<T> IEnumerable<T>.GetEnumerator() => components.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)components).GetEnumerator();

public ServiceComponentList()
{
components = new List<T>();
}

internal ServiceComponentList(List<T> initialList, bool isLastOneTheDefault)
{
components = initialList;
if (isLastOneTheDefault && initialList.Count > 0)
{
defaultComponent = initialList[initialList.Count - 1];
}
}

public void Register(T component)
{
components.Insert(0, component);
Expand All @@ -33,18 +39,25 @@ public void Register(T component)

public void Unregister(T component)
{
if (!components.Remove(component))
if (components.Remove(component))
{
if (defaultComponent.Contains(component))
if (ReferenceEquals(defaultComponent, component))
{
defaultComponent = ValueHolder<T>.Empty();
defaultComponent = default;
}
}
}

public void Unregister<TImpl>() where TImpl : T
{
componentsWithDefault.OfType<TImpl>().ToList().ForEach(component => Unregister(component));
for (var index = components.Count - 1; index >= 0; index--)
{
var component = components[index];
if (component is TImpl)
{
Unregister(component);
}
}
}

public void Replace(T oldComponent, T newComponent)
Expand All @@ -61,7 +74,9 @@ public void Replace(T oldComponent, T newComponent)

public void SetDefault(T newComponent)
{
defaultComponent = ValueHolder<T>.WithValue(newComponent);
ClearDefault();
components.Add(newComponent);
defaultComponent = newComponent;
}

public void SetDefault<TImpl>() where TImpl : T, new()
Expand All @@ -71,13 +86,16 @@ public void SetDefault(T newComponent)

public void ClearDefault()
{
defaultComponent = ValueHolder<T>.Empty();
if (defaultComponent is not null)
{
Unregister(defaultComponent);
}
}

public void Clear()
{
components.Clear();
ClearDefault();
defaultComponent = default;
}
}
}
22 changes: 13 additions & 9 deletions TechTalk.SpecFlow/Assist/SpecFlowDefaultValueComparerList.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
using TechTalk.SpecFlow.Assist.ValueComparers;
using System.Collections.Generic;
using TechTalk.SpecFlow.Assist.ValueComparers;

namespace TechTalk.SpecFlow.Assist
{
public class SpecFlowDefaultValueComparerList : ServiceComponentList<IValueComparer>
#nullable enable
internal sealed class SpecFlowDefaultValueComparerList : ServiceComponentList<IValueComparer>
{
public SpecFlowDefaultValueComparerList()
: base(new List<IValueComparer> {
new DateTimeValueComparer(),
new BoolValueComparer(),
new GuidValueComparer(),
new DecimalValueComparer(),
new DoubleValueComparer(),
new FloatValueComparer(),
new DefaultValueComparer(),
}, true)
{
Register(new DateTimeValueComparer());
Register(new BoolValueComparer());
Register(new GuidValueComparer());
Register(new DecimalValueComparer());
Register(new DoubleValueComparer());
Register(new FloatValueComparer());
SetDefault(new DefaultValueComparer());
}
}
}
54 changes: 29 additions & 25 deletions TechTalk.SpecFlow/Assist/SpecFlowDefaultValueRetrieverList.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
using TechTalk.SpecFlow.Assist.ValueRetrievers;
using System.Collections.Generic;
using TechTalk.SpecFlow.Assist.ValueRetrievers;

namespace TechTalk.SpecFlow.Assist
{
internal class SpecFlowDefaultValueRetrieverList : ServiceComponentList<IValueRetriever>
#nullable enable
internal sealed class SpecFlowDefaultValueRetrieverList : ServiceComponentList<IValueRetriever>
{
public SpecFlowDefaultValueRetrieverList()
: base(new List<IValueRetriever> {
// Sorted by likelihood
new StringValueRetriever(),
new IntValueRetriever(),
new BoolValueRetriever(),
new LongValueRetriever(),
new FloatValueRetriever(),
new DoubleValueRetriever(),
new DateTimeValueRetriever(),
new TimeSpanValueRetriever(),
new GuidValueRetriever(),
new EnumValueRetriever(),
new ListValueRetriever(),
new ArrayValueRetriever(),
new ByteValueRetriever(),
new SByteValueRetriever(),
new UIntValueRetriever(),
new ShortValueRetriever(),
new UShortValueRetriever(),
new ULongValueRetriever(),
new DecimalValueRetriever(),
new CharValueRetriever(),
new DateTimeOffsetValueRetriever(),
new UriValueRetriever()
}, false)
{
Register(new StringValueRetriever());
Register(new ByteValueRetriever());
Register(new SByteValueRetriever());
Register(new IntValueRetriever());
Register(new UIntValueRetriever());
Register(new ShortValueRetriever());
Register(new UShortValueRetriever());
Register(new LongValueRetriever());
Register(new ULongValueRetriever());
Register(new FloatValueRetriever());
Register(new DoubleValueRetriever());
Register(new DecimalValueRetriever());
Register(new CharValueRetriever());
Register(new BoolValueRetriever());
Register(new DateTimeValueRetriever());
Register(new GuidValueRetriever());
Register(new EnumValueRetriever());
Register(new TimeSpanValueRetriever());
Register(new DateTimeOffsetValueRetriever());
Register(new UriValueRetriever());

Register(new ArrayValueRetriever());
Register(new ListValueRetriever());
}
}
}
41 changes: 0 additions & 41 deletions TechTalk.SpecFlow/Assist/ValueHolder.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private IEnumerable GetItems(string[] strings, KeyValuePair<string, string> keyV
foreach (var splitValue in strings)
{
var itemKeyValuePair = new KeyValuePair<string, string>(keyValuePair.Key, splitValue.Trim());
retriever = retriever ?? GetValueRetriever(itemKeyValuePair, targetType, itemType);
retriever ??= GetValueRetriever(itemKeyValuePair, targetType, itemType);
yield return retriever?.Retrieve(itemKeyValuePair, targetType, itemType);
}
}
Expand All @@ -49,7 +49,7 @@ private IEnumerable GetItems(string[] strings, KeyValuePair<string, string> keyV

protected abstract object BuildInstance(int count, IEnumerable values, Type valueType);

private IValueRetriever GetValueRetriever(KeyValuePair<string, string> keyValuePair, Type targetType, Type valueType)
private static IValueRetriever GetValueRetriever(KeyValuePair<string, string> keyValuePair, Type targetType, Type valueType)
{
foreach (var retriever in Service.Instance.ValueRetrievers)
{
Expand Down
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
3.9.52

Changes:
+ improve Service.GetValueRetrieverFor performance

3.9.40

Changes:
Expand Down

0 comments on commit 5a732c6

Please sign in to comment.