I have a method today that works that returns a lambda expression based on a string property name, i.e. I pass in "Description" and it return a lambda of d => d.Description. This works great, but now I need to return a lambda expression given a string that contains a dot notation, i.e. I want to passing "Customer.Name" and get a lambda expression back of d => d.Customer.Name. Below is the method that I have already created that returns the 1 level lambda, but I'm not sure how to change it to the multi level.
protected dynamic CreateOrderByExpression(string sortColumn)
{
var type = typeof (TEntity);
Type entityType = null;
if (type.IsInterface)
{
var propertyInfos = new List<PropertyInfo>();
var considered = new List<Type>();
var queue = new Queue<Type>();
considered.Add(type);
queue.Enqueue(type);
while (queue.Count > 0)
{
var subType = queue.Dequeue();
foreach (var subInterface in subType.GetInterfaces().Where(subInterface => !considered.Contains(subInterface)))
{
considered.Add(subInterface);
queue.Enqueue(subInterface);
}
var typeProperties = subType.GetProperties(
BindingFlags.FlattenHierarchy
| BindingFlags.Public
| BindingFlags.Instance);
var newPropertyInfos = typeProperties
.Where(x => !propertyInfos.Contains(x));
propertyInfos.InsertRange(0, newPropertyInfos);
if (propertyInfos.All(f => f.Name != sortColumn)) continue;
entityType = subType;
break;
}
}
if (entityType == null)
{
return null;
}
var parameter = Expression.Parameter(typeof (TEntity));
var memberExpression = Expression.Property(parameter, entityType, sortColumn);
var lambdaExpression = Expression.Lambda(memberExpression, parameter);
return lambdaExpression;
}
Create a helper method like this (to be used in the bottom part of your code):
LambdaExpression GetLambdaExpression(Type type, IEnumerable<string> properties)
{
Type t = type;
ParameterExpression parameter = Expression.Parameter(t);
Expression expression = parameter;
for (int i = 0; i < properties.Count(); i++)
{
expression = Expression.Property(expression, t, properties.ElementAt(i));
t = expression.Type;
}
var lambdaExpression = Expression.Lambda(expression, parameter);
return lambdaExpression;
}
Now use it like this:
GetLambdaExpression(typeof(Outer), new[] { "InnerProperty", "MyProperty" });
For the following classes:
class Outer
{
public Inner InnerProperty { get; set; }
}
class Inner
{
public int MyProperty { get; set; }
}
I know it could have been a little more suited to your original code but I guess you can go from here (like converting the string with dots into an array). And I know it could have been done using recursion but I got a headache today...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With