I'm using an
Expression<Func<T, object?>> DatabaseProjection which defines what values I want to extract from T. In specific case, I will get a list of objects (string or int):
DatabaseProjection = p => p.Voyages.SelectMany(v => v.Passages.Select(p => p.Location.Name))
Then, I pass some value, which must be used to check if any of the elements in the retrived list fulfills a condition. Condition is got from a method:
private static Expression GetExpression
(ConditionType conditionType, InvocationExpression invokedProjection, ConstantExpression value) => conditionType switch
{
ConditionType.Is => Expression.Equal(invokedProjection, value),
_ => throw new NotImplementedException($"{conditionType} is not supported."),
};
This is the method that should build an expression on the list:
public static Expression CreateExpression(Condition condition, Expression projection, ParameterExpression parameter)
{
var invokedProjection = Expression.Invoke(projection, parameter);
//ConstantExpression value;
if (invokedProjection.Type.GetInterfaces().Contains(typeof(IList)))
{
var containsMethod = typeof(IList).GetMethod("Contains", new Type[] { typeof(IList) });
var genericType = invokedProjection.Type.GetTypeInfo().GetGenericArguments().First();
var castValue = string.IsNullOrWhiteSpace(condition.Value) && genericType.IsValueType
? Activator.CreateInstance(genericType)
: Convert.ChangeType(condition.Value, genericType);
var value = Expression.Constant(castValue, genericType);
var contExp = Expression.Call(containsMethod!, invokedProjection, GetExpression(condition.Type, **invokedProjection**, value));
return Expression.Constant(false);
}
}
I kno, that invokedProjection cannot be passed to GetProjection method because it's not possible to compare value (which is string type) to a list of strings. But I'm out of ideas what could be done here. In general, I must do something like LINQ:
list.Contains(el => el.Name == name)
The inner part is done in GetProjection, but how to make the iteration over the "list" to check the conditions for each of element?
Here is a call of CreateExpression method:
private static Expression CreateFilterExpression(Alert alert, ParameterExpression parameter, Func<string, Expression> createProjection)
{
var conditionExpression = ExpressionFactory.CreateExpression(condition, projectionExpression, parameter);
return expression;
}
