Skip to content

Commit

Permalink
Enhance expression handling and refactoring
Browse files Browse the repository at this point in the history
Refactored `ContentItemQueryExpressionVisitor.cs` to make `ExtractFieldValues` and `GetExpressionValue` methods static, improving design by eliminating the need for class instances for these operations. Added multiple new methods and `using` directives in `ExpressionExtensions.cs` to expand expression handling capabilities, including reflection and collection processing. Introduced utility methods for more efficient and flexible value extraction from expressions, supporting a variety of types and scenarios. These changes significantly enhance the utility and maintainability of the `XperienceCommunity.DataContext` namespace, making the data context more dynamic and capable of handling a broader range of data manipulation and querying scenarios.
  • Loading branch information
bluemodus-brandon committed Jul 12, 2024
1 parent bd4005e commit 39417b0
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,13 @@ private void AddWhereInCondition(string columnName, IEnumerable<object>? values)
return null;
}

private IEnumerable<object> ExtractFieldValues(MemberExpression fieldExpression)
private static IEnumerable<object> ExtractFieldValues(MemberExpression fieldExpression)
{
var value = GetExpressionValue(fieldExpression);
return ExtractValues(value);
}

private object? GetExpressionValue(Expression expression)
private static object? GetExpressionValue(Expression expression)
{
switch (expression)
{
Expand Down
120 changes: 119 additions & 1 deletion src/XperienceCommunity.DataContext/Extensions/ExpressionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,72 @@
using System.Linq.Expressions;
using System.Collections;
using System.Linq.Expressions;
using System.Reflection;

namespace XperienceCommunity.DataContext.Extensions
{
internal static class ExpressionExtensions
{
/// <summary>
/// Extracts the values from a collection expression.
/// </summary>
/// <param name="collectionExpression">The collection expression.</param>
/// <returns>The extracted values as an enumerable of objects.</returns>
internal static IEnumerable<object>? ExtractCollectionValues(this MemberExpression collectionExpression)
{
if (collectionExpression.Expression != null)
{
var value = GetExpressionValue(collectionExpression.Expression);

return ExtractValues(value);
}

return null;
}

/// <summary>
/// Extracts the values from a field expression.
/// </summary>
/// <param name="fieldExpression">The field expression.</param>
/// <returns>The extracted values as an enumerable of objects.</returns>
internal static IEnumerable<object> ExtractFieldValues(this MemberExpression fieldExpression)
{
var value = GetExpressionValue(fieldExpression);
return ExtractValues(value);
}

/// <summary>
/// Gets the value of an expression.
/// </summary>
/// <param name="expression">The expression.</param>
/// <returns>The value of the expression.</returns>
internal static object? GetExpressionValue(Expression expression)
{
switch (expression)
{
case ConstantExpression constantExpression:
return constantExpression.Value!;

case MemberExpression memberExpression:
var container = GetExpressionValue(memberExpression.Expression!);
var member = memberExpression.Member;
switch (member)
{
case FieldInfo fieldInfo:
return fieldInfo.GetValue(container);

case PropertyInfo propertyInfo:
return propertyInfo.GetValue(container);

default:
throw new NotSupportedException(
$"The member type '{member.GetType().Name}' is not supported.");
}
default:
throw new NotSupportedException(
$"The expression type '{expression.GetType().Name}' is not supported.");
}
}

/// <summary>
/// Gets the member name from a method call expression.
/// </summary>
Expand All @@ -18,5 +81,60 @@ internal static class ExpressionExtensions

return null;
}

private static IEnumerable<object> ExtractValues(object? value)
{
if (value is null)
{
return [];
}

if (value is IEnumerable<object> objectEnumerable)
{
return objectEnumerable;
}

if (value is IEnumerable<int> intEnumerable)
{
return intEnumerable.Cast<object>();
}

if (value is IEnumerable<string> stringEnumerable)
{
return stringEnumerable.Cast<object>();
}

if (value is IEnumerable<Guid> guidEnumerable)
{
return guidEnumerable.Cast<object>();
}

if (value is IEnumerable enumerable)
{
var list = new List<object>();

foreach (var item in enumerable)
{
var itemValues = ExtractValues(item);
list.AddRange(itemValues);
}

return list;
}

// Check if the object has a property that is a collection
var properties = value.GetType().GetProperties();

var collectionProperty = properties.FirstOrDefault(p =>
p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>));

if (collectionProperty != null)
{
var collectionValue = collectionProperty.GetValue(value);
return ExtractValues(collectionValue);
}

return new[] { value };
}
}
}

0 comments on commit 39417b0

Please sign in to comment.