該物業目前已經困擾我好幾天了....創建表達式樹分配到列表
如果我有我自己的對象的列表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