I want to dynamically apply a predicates to a list of dynamic object. My solution is working well when I use actual objects but it does not work on dynamic objects and I can't figure out what is the problem.
Note: I searched Stackoverflow none of similar questions are using list of dynamic objects.
I have a list of dynamic objects like the following code. The list contains two dynamic object that have two properties (Name,CreateDate). I used JsonConvert class to create dynamic objects :
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();
As you see lst is a list of dynamic objects and have 2 items in it.
Now I want to filter list to get the item with the name Jonh (p=> p.Name == "john")
To do this I had the following approach:
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 !
The lst2 should contain 1 item but it contains 0 items. But if I change the original list(lst) to a type that has a Name property (let's say List<Person>) it lst2 correctly have 1 item.
UPDATE:
Even when I use ExpandoObject to create dynamic objects it still won't work :
dynamic obj = new ExpandoObject();
var dictionary = (IDictionary<string, object>)obj;
dictionary.Add("Name", "John");
dictionary.Add("CreateDate", DateTime.Now);
UPDATE 2:
As pionted out in the comments ExpandoObject actually works and the problem is with SqlDataReader. Here are what I have tried (see Not working comments in the following code) :
...
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);
}
...