Являются ли динамические члены несовместимыми с динамическими запросами Linq? Или существует другой способ построения выражений, которые будут правильно оцениваться при работе с членами типа dynamic ?
Оба могут работать вместе. Просто сделайте преобразование в Int32 перед тем, как сделать сравнение следующим образом:
IEnumerable<DataItem> result =
repository.AsQueryable<DataItem>().Where("Int32(it[\"Age\"]) == 30");
Редактировать 1: Сказав это, использование динамического связывания в связи с Linq в целом ограничено, так как динамические операции недопустимы в деревьях выражений. Рассмотрим следующий запрос Linq-To-Objects:
IEnumerable<DataItem> result = repository.AsQueryable().
Where(d => d["Age"] == 30);
Этот фрагмент кода не будет компилироваться по причине, указанной выше.
Edit 2: В вашем случае (и в сочетании с Dynamic Linq) есть несколько способов взломать себя вокруг проблем, упомянутых в Edit 1 и в первоначальном вопросе. Например:
// Variant 1: Using strings all the way
public void DynamicQueryExample(string property, dynamic val)
{
List<DataItem> repository = new List<DataItem>(){
new DataItem() {
new Data("Name", "Mike"),
new Data("Age", 25),
new Data("BirthDate", new DateTime(1987, 1, 5))
},
new DataItem() {
new Data("Name", "Steve"),
new Data("Age", 30),
new Data("BirthDate", new DateTime(1982, 1, 10))
}
};
// Use string comparison all the time
string predicate = "it[\"{0}\"].ToString() == \"{1}\"";
predicate = String.Format(whereClause , property, val.ToString());
var result = repository.AsQueryable<DataItem>().Where(predicate);
if (result.Count() == 1)
Console.WriteLine(result.Single()["Name"]);
}
Program p = new Program();
p.DynamicQueryExample("Age", 30); // Prints "Steve"
p.DynamicQueryExample("BirthDate", new DateTime(1982, 1, 10)); // Prints "Steve"
p.DynamicQueryExample("Name", "Mike"); // Prints "Steve" (nah, just joking...)
или
// Variant 2: Detecting the type at runtime.
public void DynamicQueryExample(string property, string val)
{
List<DataItem> repository = new List<DataItem>(){
new DataItem() {
new Data("Name", "Mike"),
new Data("Age", 25),
new Data("BirthDate", new DateTime(1987, 1, 5))
},
new DataItem() {
new Data("Name", "Steve"),
new Data("Age", 30),
new Data("BirthDate", new DateTime(1982, 1, 10))
}
};
string whereClause = "{0}(it[\"{1}\"]) == {2}";
// Discover the type at runtime (and convert accordingly)
Type type = repository.First()[property].GetType();
string stype = type.ToString();
stype = stype.Substring(stype.LastIndexOf('.') + 1);
if (type.Equals(typeof(string))) {
// Need to surround formatting directive with ""
whereClause = whereClause.Replace("{2}", "\"{2}\"");
}
string predicate = String.Format(whereClause, stype, property, val);
var result = repository.AsQueryable<DataItem>().Where(predicate);
if (result.Count() == 1)
Console.WriteLine(result.Single()["Name"]);
}
var p = new Program();
p.DynamicQueryExample("Age", "30");
p.DynamicQueryExample("BirthDate", "DateTime(1982, 1, 10)");
p.DynamicQueryExample("Name", "Mike");