该物业目前已经困扰我好几天了....创建表达式树分配到列表
如果我有我自己的对象的列表SearchResults
和SearchResult所包含对象的多个列表,所有这些都匹配(布尔)属性,我怎样才能重新表达式树来实现以下目标:
//searchResults is a List<SearchResults>
searchResults[i].Comments = searchResults[i].Comments.Select(p1 =>
{
p1.Match = ListOfStringVariable.All(p2 =>
{
string value = (string)typeof(CommentData).GetProperty(propertyName).GetValue(p1);
return value.Contains(p2);
});
return p1;
}).OrderByDescending(x => x.Match);
....
public class SearchResults
{
public IEnumerable<CommentData> Comments { get; set; }
public IEnumerable<AdvisorData> Advisors { get; set; }
}
public class CommentData
{
public string CommentText { get; set; }
public bool Match { get; set; }
}
public class AdvisorData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Match { get; set; }
}
,因为我不知道在编译时需要被赋予的属性所需要的表达式树,无论是它是评论,顾问等(因为这是一个更大问题的简化)。上面的例子仅用于评论,那么如何在没有条件块的情况下使用相同的代码来分配给顾问?
非常感谢
更新:
到目前为止,使用反射,我们有以下的StriplingWarrior
var searchResult = searchResults[i];
foreach (var srProperty in searchResultsProperties)
{
var collectionType = srProperty.PropertyType;
if(!collectionType.IsGenericType || collectionType.GetGenericTypeDefinition() != typeof(IEnumerable<>))
{
throw new InvalidOperationException("All SearchResults properties should be IEnumerable<Something>");
}
var itemType = collectionType.GetGenericArguments()[0];
var itemProperties = itemType.GetProperties().Where(p => p.Name != "Match");
var items = ((IEnumerable<IHaveMatchProperty>) srProperty.GetValue(searchResult))
// Materialize the enumerable, in case it's backed by something that
// would re-create objects each time it's iterated over.
.ToList();
foreach (var item in items)
{
var propertyValues = itemProperties.Select(p => (string)p.GetValue(item));
item.Match = propertyValues.Any(v => searchTerms.Any(v.Contains));
}
var orderedItems = items.OrderBy(i => i.Match);
srProperty.SetValue(srProperty, orderedItems);
}
然而orderedItems
是System.Linq.OrderedEnumerable<IHaveMatchProperty,bool>
型的,需要转换为IEnumerable<AdvisorData>
。下面将引发错误:
'System.Linq.Enumerable.CastIterator(System.Collections.IEnumerable)' 是 '方法',但使用像 '类型'
var castMethod = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(new[] {propertyType});
var result = castMethod.Invoke(null, new[] { orderedItems });
其中propertyType
是类型AdvisorData
1.你真的不应该在'Select()'lambda中设置属性。 2.你肯定需要表达树吗?如果你使用的是LINQ到对象,你应该能够通过一些基本的反思来获得。 3.您可以考虑使用另一个类,例如'SearchResults',它具有'Match'属性,而不是将匹配属性放在结果上。如果你是肯定的,你需要CommentData等有一个Match属性,如果你让它们在它上面实现一个与该属性的接口,你可能会让它更容易。 –
StriplingWarrior
2014-11-06 19:17:46
@StriplingWarrior选择中的分配以便我不必完全重新创建新列表。我如何使用反射来创建上述?它似乎超出了仅仅反思的范围。另外,我也提到了MatchData接口和Match属性,但现在已经删除了它,因为它简化了我的开发过程并且很容易重新引入。非常感谢 – tic 2014-11-06 19:36:57
我知道你为什么选择将作业放在那里。这仍然是不好的做法。如果您要将注释视为集合并对其进行修改,请使用'for'循环。无论如何,上面的代码已经使用反射来获取CommentData上的属性值。迭代所有SearchResults的值也不应该太大。你需要哪些帮助? (尽量保持您的问题尽可能具体。) – StriplingWarrior 2014-11-06 20:13:53