Я хочу динамически применять предикаты к списку динамических объектов.Мое решение работает хорошо, когда я использую реальные объекты, но оно не работает с динамическими объектами, и я не могу понять, в чем проблема.
Примечание: я искал Stackoverflow, ни один из подобных вопросов не используетсписок динамических объектов.
У меня есть список динамических объектов, подобных следующему коду.Список содержит два динамических объекта, которые имеют два свойства (Name
, CreateDate
).Я использовал класс JsonConvert
для создания динамических объектов:
var lst = new List<dynamic>();
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add("Name", "John");
dict.Add("CreateDate", DateTime.Now);
lst.Add(JsonConvert.DeserializeObject<dynamic>(JsonConvert.SerializeObject(dict)));
dict.Clear();
dict.Add("Name", "sara");
dict.Add("CreateDate", DateTime.Now);
lst.Add(JsonConvert.DeserializeObject<dynamic>(JsonConvert.SerializeObject(dict)));
dict.Clear();
Как видите, lst
представляет собой список динамических объектов и содержит 2 элемента.Теперь я хочу отфильтровать список, чтобы получить элемент с именем Jonh (p=> p.Name == "john"
)
. Для этого у меня был следующий подход:
ParameterExpression pe = Expression.Parameter(typeof(object), "p");
CallSiteBinder name = Binder.GetMember(CSharpBinderFlags.None, "Name", typeof(object),
new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var pname = Expression.Dynamic(name, typeof(object), pe);
var right = Expression.Constant("John");
Expression e2 = Expression.Equal(pname, right);
var qu = Expression.Lambda<Func<dynamic, bool>>(e2, pe);
var lst2 = lst.AsQueryable().Where(qu).ToList();// Count()==0 !
lst2
должен содержать 1элемент, но он содержит 0 элементов.Но если я изменю исходный список (lst
) на тип, у которого есть свойство Name
(скажем, List<Person>
), то lst2
будет правильно содержать 1 элемент.
ОБНОВЛЕНИЕ: Даже когда я использую ExpandoObject
для создания динамических объектов, он все равно не будет работать:
dynamic obj = new ExpandoObject();
var dictionary = (IDictionary<string, object>)obj;
dictionary.Add("Name", "John");
dictionary.Add("CreateDate", DateTime.Now);
ОБНОВЛЕНИЕ 2: Как указано в комментариях ExpandoObject
на самом деле работает ипроблема с SqlDataReader
.Вот что я попробовал (см. Не работает комментарии в следующем коде):
...
List<dynamic> result = new List<dynamic>();
While(dr.Read()){
dynamic obj = new ExpandoObject();
var dictionary = (IDictionary<string, object>)obj;
dictionary.Add("Name","John"); // <= this works fine
// dictionary.Add("Name",dr["Name"]); // <= Not working
// dictionary.Add("Name",dr["Name"].ToItsType()); // <= Not working
// dictionary.Add("Name",dr["Name"].ToString()); // <= Not working
dictionary.Add("CreateDate", DateTime.Now);
result.Add(obj);
}
...