有人想帮助我成为更好的程序员吗?
我有一个应用程序,我按照各种标准过滤对象集合。现在我的代码工作,但90%是重复的,我觉得这意味着我做错了什么。关于如何制作更多可重复使用的过滤代码的任何建议?
假设我有一组像这样的对象:
public class ExampleData
{
public int SomeValue1 { get; set; }
public int SomeValue2 { get; set; }
public int SomeValue3 { get; set; }
public string SomeValue4 { get; set; }
}
这是我的过滤器类。查看代码注释。
class ExampleFilter
{
public ExampleFilter()
{
}
public IEnumerable<ExampleData> applyFilters(SearchCriteria criteria, IEnumerable<ExampleData> data)
{
//The body of these methods is almost identical...how can I better design this process so I don't cut and paste 90% of the code?
data = filterByValue1Selections(criteria.FormTemplateSelected, data);
data = filterByValue2Selections(criteria.FormTemplateSelected, data);
return data;
}
public IEnumerable<ExampleData> filterByValue1Selections(List<int> value1Ids, IEnumerable<ExampleData> data)
{
if (value1Ids != null)
{
IEnumerable<ExampleData> dataQuery = null;
foreach (int selectedValueIds in value1Ids)
{
//See http://justgeeks.blogspot.com/2011/01/using-linq-in-foreach-loop-to-build.html
//For explanation of why we copy this locally
int selectedId = selectedValueIds;
if (dataQuery == null)
{
//This code and the similar block in the else are the only differences in these methods
dataQuery = data.Where(t => t.SomeValue1 == selectedId);
}
else
{
dataQuery = dataQuery.Union(data.Where(t => t.SomeValue1 == selectedId));
}
}
data = dataQuery;
}
return data;
}
public IEnumerable<ExampleData> filterByValue2Selections(List<int> value2Ids, IEnumerable<ExampleData> data)
{
if (value2Ids != null)
{
IEnumerable<ExampleData> dataQuery = null;
foreach (int selectedValueIds in value2Ids)
{
//See http://justgeeks.blogspot.com/2011/01/using-linq-in-foreach-loop-to-build.html
//For explanation of why we copy this locally
int selectedId = selectedValueIds;
if (dataQuery == null)
{
dataQuery = data.Where(t => t.SomeValue1 == selectedId);
}
else
{
dataQuery = dataQuery.Union(data.Where(t => t.SomeValue1 == selectedId));
}
}
data = dataQuery;
}
return data;
}
}
答案 0 :(得分:2)
您基本上是在重新实施Contains()
方法 - 您可以这样做:
List<int> valueIds = ...;
var filteredData = data.Where(x=> valueIds.Contains(x.SomeValue1));
然后你的applyFilters方法如下所示:
public IEnumerable<ExampleData> applyFilters(SearchCriteria criteria, IEnumerable<ExampleData> data)
{
data = data.Where(x=> criteria.FormTemplateSelected.Contains(x.SomeValue1)
&& criteria.FormTemplateSelected.Contains(x.SomeValue2));
return data;
}
答案 1 :(得分:1)
一般情况下,您可以使用Func<T, TResult> delegates
来概括重复的FilterByValue
方法,您可以尝试这样的方法(伪代码):
public IEnumerable<T> FilterByValue<T>(List<int> value1Ids, IEnumerable<T> data, Func<T, int> selector)
{
if (value1Ids != null)
{
IEnumerable<ExampleData> dataQuery = null;
foreach (int id in value1Ids)
{
int selectedId = id;
if (dataQuery == null)
{
dataQuery = data.Where(x => selector(x) == id);
}
else
{
dataQuery = dataQuery.Union(data.Where(x => selector(x) == id));
}
}
data = dataQuery;
}
return data;
}
这样您就可以传递实际的属性选择:
FilterByValue(criteria.FormTemplateSelected, data, x => SomeValue1);
FilterByValue(criteria.FormTemplateSelected, data, x => SomeValue2);
根据具体情况,您可以更进一步,在代表身上应用更复杂的逻辑,但很难从您粘贴的代码中判断出您最感兴趣的部分。