Если у вас есть только один класс, имеющий это требование с ограниченным числом свойств, скажем, менее 20, я бы не стал создавать универсальное решение для этого. Код Where
, который проверяет все свойства. Это имеет то преимущество, что если в будущем кто-то изменит или удалит свойство, ваш компилятор будет жаловаться.
Хорошим решением было бы дать вашему классу функцию расширения:
public static bool HasNullProperties(this MyClass x)
{
return x.Name == null
&& x.Location == null
&& x.OrderSize == null
...;
}
public static IEnumerable<MyClass> WhereHasNullProperties(this IEnumerable<MyClass> source)
{
return source.Where(item => item.HasNullProperties();
}
Использование где-то в операторе LINQ
var result = dbContext.MyItems.WhereHasNullProperties()
.GroupBy(...)
.Select(...);
Если вы хотите получить полное пробное решение, которое работает на нескольких классах, подумайте о разработке интерфейса:
interface IHasNullProperties
{
bool HasNullProperties {get;}
}
Ваша функция LINQ будет:
public static IEnumerable<TSource> WhereHasNullProperties<TSource>(
this IEnumerable<TSource> source)
where TSource : IHasNullProperties
{
return source.Where(item => item.HasNullProperties();
}
Наконец, относительно медленным методом было бы использовать отражение: для любого класса получить все его свойства get, которые можно обнулять, и посмотреть, имеет ли какое-либо из них нулевое значение:
static bool HasNullPrperties<TSource>(this TSource source)
where TSource : class
{
// Take the type of the source, and get all properties of this type
var result = source.GetType().GetProperties()
// keep only the readable properties (so you can do GetValue)
// and those properties that have a nullable type
.Where(property => property.CanRead
&& Nullable.GetUnderlyingType(property.Type) != null)
// for every of this properties, ask the source object for the property value:
.Select(property => property.GetValue(source))
// and keep only the properties that have a null value
.Where(value => value == null);
// return true if source has any property with a null value
// = if there is any value left in my sequence
.Any();
return result;
}