Just something I decided to try cobbling together tonight. Didn't take more than a few minutes, trying to type quietly (didn't want to wake anyone).
It allows you to do things like:
var q = db.Customers.Where(new Customer { CustomerID = "EASTC" });
Basically, it's a where-by-prototype. One obvious function, as seen above, is to get a LINQ to SQL entity by ID.
Here's the code:
public static IQueryable<TEntity> Where<TEntity>(
this IQueryable<TEntity> seq, TEntity entity
)
{
IQueryable<TEntity> result = seq;
var memberTypes = new[] { MemberTypes.Property, MemberTypes.Field };
var members = typeof(TEntity).GetMembers()
.Where(mi => memberTypes.Contains(mi.MemberType)
&& mi.GetCustomAttributes(typeof(ColumnAttribute), true)
.Length > 0);
foreach (var member in members)
{
var isField = member.MemberType == MemberTypes.Field;
var memberAsField = member as FieldInfo;
var memberAsProperty = member as PropertyInfo;
var memberValue = isField ? memberAsField.GetValue(entity)
: memberAsProperty.GetValue(entity, null);
var memberIsRefType = (isField ? memberAsField.FieldType
: memberAsProperty.PropertyType
).IsClass;
var memberIsDefaultValue = (memberValue == (memberIsRefType ? (object)null
: (object)0
));
if (memberIsDefaultValue)
{
continue;
}
var parameter = Expression.Parameter(typeof(TEntity), "p");
var memberAccess = Expression.MakeMemberAccess(parameter, member);
var value = Expression.Constant(memberValue);
var equality = Expression.Equal(memberAccess, value);
var predicate = Expression.Lambda<Func<TEntity, bool>>(equality, parameter);
result = result.Where(predicate);
}
return result;
}