Одна вещь, которую вы могли бы рассмотреть, - это упростить ваш пользовательский интерфейс, сняв флажки и используя вместо этого элемент «<empty>
» или «<null>
» в раскрывающемся списке. Это уменьшит количество элементов управления, занимающих место в вашем окне, устранит необходимость в сложной логике «разрешить X только если Y не отмечен» и позволит создать красивое поле «один элемент управления на запрос».
Переходя к логике запроса результатов, я бы начал с создания простого объекта, представляющего фильтр для объекта вашего домена:
interface IDomainObjectFilter {
bool ShouldInclude( DomainObject o, string target );
}
Вы можете связать соответствующий экземпляр фильтра с каждым из ваших элементов управления пользовательского интерфейса, а затем получить его, когда пользователь инициирует запрос:
sealed class FileNameFilter : IDomainObjectFilter {
public bool ShouldInclude( DomainObject o, string target ) {
return string.IsNullOrEmpty( target )
|| o.FileName.Contains( target );
}
}
...
ddlFileName.Tag = new FileNameFilter( );
Затем вы можете обобщить фильтрацию результатов, просто перечислив элементы управления и выполнив соответствующий фильтр (спасибо hurst за обобщенную идею):
var finalResults = ddlControls.Aggregate( initialResults, ( c, r ) => {
var filter = c.Tag as IDomainObjectFilter;
var target = c.SelectedValue;
return r.Where( o => filter.ShouldInclude( o, target ) );
} );
Поскольку ваши запросы настолько регулярны, вы могли бы еще больше упростить реализацию, используя единственный класс фильтра, принимающий селектор члена:
sealed class DomainObjectFilter {
private readonly Func<DomainObject,string> memberSelector_;
public DomainObjectFilter( Func<DomainObject,string> memberSelector ) {
this.memberSelector_ = memberSelector;
}
public bool ShouldInclude( DomainObject o, string target ) {
string member = this.memberSelector_( o );
return string.IsNullOrEmpty( target )
|| member.Contains( target );
}
}
...
ddlFileName.Tag = new DomainObjectFilter( o => o.FileName );