为什么 ExpandoObject 在 Guid 转换为字符串时无法正常工作?



如果您传递两个字符串,我有一段代码可以正常工作。由于某些原因,如果您传递转换为字符串的GUID,它的工作方式就不一样了。

更详细地说,如果我创建一个新的ExpandoObject并传递字符串值,它会起作用,但如果我传递转换为字符串的GUID,它就不会起作用。

下面的代码应该比较两个参数。在我的例子中,我传递相同的两个字符串。使用Equal运算符时,如果字符串相同,则应返回true。如果第二个参数GUID转换为字符串,则返回false,即使字符串相同。dynamicObj.Add(memberName, Guid.Parse(value).ToString());

不确定我错过了什么。这是我的密码。

 string value = "642188c7-8e10-e111-961b-0ee1388ccc3b";
 string memberName = "State";
 string contactValue = value;
 var dynamicObj = (IDictionary<string, object>)new ExpandoObject();   dynamicObj.Add(memberName, Guid.Parse(value).ToString());
 var expression = Expression.Parameter(typeof(object), "arg");
 var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, null, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
 var property = Expression.Dynamic(binder, typeof(object), expression);
 var isValid = false;
 var right = Expression.Constant(contactValue);
 var result = Expression.MakeBinary(ExpressionType.Equal, property, right);
 var func = typeof(Func<,>).MakeGenericType(dynamicObj.GetType(), typeof(bool));
 var expr = Expression.Lambda(func, result, expression).Compile();
 isValid = (bool)expr.DynamicInvoke(dynamicObj);

GUID解析将使用与仅使用字符串文字相同的字符串(值)。

然而,不同之处在于它在字典中的存储方式:它的类型是Dictionary<string, object>。这意味着将使用Object类及其==运算符来进行引用相等性检查。然而,String类通过执行值相等性检查来重载此项。

这就是为什么这是真的:

Console.WriteLine(value == Guid.Parse(value).ToString());

返回false时:

Console.WriteLine((object) value == (object) Guid.Parse(value).ToString());

由于字符串是不可变的,Guid.Parse(value).ToString()将创建一个新的string对象,并与contactValue(与value相同)进行引用相等性检查。与一直使用返回truevalue相比,这显然会返回false,因为您永远不会创建新对象。

为了使其工作,您可以将动态操作数强制转换为string,这样它将使用正确的重载:

var castDyn = Expression.Convert(property, typeof(string));
var result = Expression.MakeBinary(ExpressionType.Equal, castDyn, right);

最新更新