Skip to content

Commit

Permalink
Fixed behavior to return false and the default value when no element …
Browse files Browse the repository at this point in the history
…is found at the specified index in a path.
  • Loading branch information
hennadiilu committed May 4, 2024
1 parent c1b294e commit 9f5d1cb
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 13 deletions.
9 changes: 8 additions & 1 deletion src/Heleonix.Reflection/Reflector.Get.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,14 @@ public static bool Get<TReturn>(

if (index != null)
{
container = GetElementAt(container, index);
var isElementFound = GetElementAt(container, index, out container);

if (!isElementFound)
{
value = default;

return false;
}

if (container == null)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Heleonix.Reflection/Reflector.Set.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,9 @@ private static bool Set(
{
if (dot != -1)
{
container = GetElementAt(container, index);
var isElementFound = GetElementAt(container, index, out container);

if (container == null)
if (!isElementFound || container == null)
{
return false;
}
Expand Down
34 changes: 24 additions & 10 deletions src/Heleonix.Reflection/Reflector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,49 +72,63 @@ private static bool ParameterTypesMatch(ParameterInfo[] paramInfos, Type[] param
/// </summary>
/// <param name="container">A container to get an element from.</param>
/// <param name="index">An index to get an elementa at.</param>
/// <returns>An element by the specified <paramref name="index"/>.</returns>
private static object GetElementAt(object container, object index)
/// <param name="element">The elemebt retrieved by the specified <paramref name="index"/> or null.</param>
/// <returns><c>true</c>, if an element is found by the specified <paramref name="index"/>, otherwise <c>false</c>.</returns>
private static bool GetElementAt(object container, object index, out object element)
{
if (container is IDictionary dictionary)
{
foreach (var key in dictionary.Keys)
{
if (key.Equals(index) || Convert.ToString(key) == Convert.ToString(index))
{
return dictionary[key];
element = dictionary[key];

return true;
}
}

return null;
element = null;

return false;
}

var intIndex = (int)index;

if (container is IList list)
{
if ((int)index >= list.Count)
if (intIndex >= list.Count)
{
return null;
element = null;

return false;
}

return list[(int)index];
element = list[intIndex];

return true;
}

if (container is IEnumerable enumerable)
{
var enumerator = enumerable.GetEnumerator();
var intIndex = (int)index;

while (enumerator.MoveNext())
{
if (intIndex == 0)
{
return enumerator.Current;
element = enumerator.Current;

return true;
}

intIndex--;
}
}

return null;
element = null;

return false;
}

/// <summary>
Expand Down
23 changes: 23 additions & 0 deletions test/Heleonix.Reflection.Tests/Reflector.Get.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,17 @@ public static void Get()
Assert.That(returnValue, Is.True);
});
});

And("the index is out of range", () =>
{
memberPath = "ItemsProperty[11111]";

Should("provide default value and return false", () =>
{
Assert.That(result, Is.Null);
Assert.That(returnValue, Is.False);
});
});
});

And("the indexer is in a middle of the memberPath", () =>
Expand Down Expand Up @@ -270,6 +281,18 @@ public static void Get()
Assert.That(returnValue, Is.False);
});
});

And("the item by the specified index is null", () =>
{
instance.SubItemProperty.SubSubItemsListProperty[0] = null;
memberPath = "SubItemProperty.SubSubItemsListProperty[0].TextProperty";

Should("provide default value and return false", () =>
{
Assert.That(result, Is.Null);
Assert.That(returnValue, Is.False);
});
});
});

And("the collection is not a list", () =>
Expand Down

0 comments on commit 9f5d1cb

Please sign in to comment.