gpt4 book ai didi

c# - 动态表达式不适用于动态对象

转载 作者:行者123 更新时间:2023-12-04 01:49:20 25 4
gpt4 key购买 nike

我想动态地将谓词应用于动态对象列表。当我使用实际对象时,我的解决方案运行良好,但它不适用于动态对象,我无法弄清楚是什么问题。

注意:我搜索了 Stackoverflow,没有一个类似的问题使用动态对象列表。

我有一个动态对象列表,如以下代码。该列表包含两个具有两个属性的动态对象( NameCreateDate )。我用过 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);
}
...

最佳答案

我能够通过更改 ExpandoObject 重现该问题(在您的 UPDATE 2 给了我这个想法之后)示例代码

dictionary.Add("Name", "John");


dictionary.Add("Name", new string("John".ToCharArray()));

避免常数 string实习,这将我们引向动态表达式代码中的问题。

动态表达式类型为 object ,因此 Expression.Equal解析为 对象 运算符(operator) == ,即 ReferenceEquals .这就是该示例使用常量字符串而不是运行时创建的字符串的原因。

您在这里需要的是使用实际的属性类型。因此,只需将动态属性访问器的结果( Expression.Convert )转换为预期类型:
var pname = Expression.Convert(Expression.Dynamic(name, typeof(object), pe), typeof(string));

现在引用 pname 的表达式表达式将解析为正确的类型(在这种特殊情况下, Equal 将解析为重载的字符串 == 运算符,它可以正确地按值比较字符串。对于像 intDateTime 等值类型也是如此)。

关于c# - 动态表达式不适用于动态对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53985129/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com