Skip to content

Instantly share code, notes, and snippets.

@svrooij
Created November 13, 2019 13:51
Show Gist options
  • Save svrooij/8fef0289385257722fd344e79ad2e84a to your computer and use it in GitHub Desktop.
Save svrooij/8fef0289385257722fd344e79ad2e84a to your computer and use it in GitHub Desktop.
Select some properties based on $select query
// Generic version created from this sample https://stackoverflow.com/a/58836648/639153
public static class IQueryableExtensions {
public static IQueryable<TSource> SelectProperties<TSource>(
this IQueryable<TSource> sources,
ISet<string> propertiesToSelect)
{
if (sources == null) throw new ArgumentNullException(nameof(sources));
if (propertiesToSelect == null) throw new ArgumentNullException(nameof(propertiesToSelect));
// Check if properties exist in TSource
var properties = typeof(TSource).GetProperties().Where(p => propertiesToSelect.Contains(p.Name)).Select(p => p.Name);
if (!properties.Any()) throw new ArgumentException("Specified properties not found", nameof(propertiesToSelect));
var type = typeof(TSource);
// p =>
var parameter = Expression.Parameter(type, "p");
// create bindings for initialization
var bindings = properties
.Select(s => {
// property
var property = type.GetProperty(s);
// original value
var propertyExpression = Expression.Property(parameter, property);
// set value "Property = p.Property"
return Expression.Bind(property, propertyExpression);
}
);
// new TSource()
var newViewModel = Expression.New(type);
// new TSource { Property1 = p.Property1, ... }
var body = Expression.MemberInit(newViewModel, bindings);
// p => new TSource { Property1 = p.Property1, ... }
var selector = Expression.Lambda<Func<TSource, TSource>>(body, parameter);
return sources.Select(selector);
}
public static IQueryable<TSource> SelectProperties<TSource>(this IQueryable<TSource> sources, string propertiesToSelect)
{
if (sources == null) throw new ArgumentNullException(nameof(sources));
if (propertiesToSelect == null) throw new ArgumentNullException(nameof(propertiesToSelect));
HashSet<string> names = new HashSet<string>();
var properties = propertiesToSelect.Split(',');
foreach (var p in properties)
{
names.Add(p);
}
return sources.SelectProperties(names);
}
}
// Use the IQueryableExtensions on some IQueryable
someDbContext.People.AsQueryable().SelectProperties("Id,DisplayName,...")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment