我有一个匿名类型对象,它是从一个方法接收到的动态对象 我想检查该对象上存在的属性。
.... var settings = new { Filename="temp.txt", Size=10 } ... function void Settings(dynamic settings) { var exists = IsSettingExist(settings,"Filename") }
如何实现 IsSettingExist?
如果您可以控制创建/传递设置对象,那么我建议您使用 ExpendoObject 来代替。
dynamic settings = new ExpandoObject(); settings.Filename = "asdf.txt"; settings.Size = 10; ... function void Settings(dynamic settings) { if ( ((IDictionary<string, object>)settings).ContainsKey("Filename") ) .... do something .... }
public static bool DoesPropertyExist(dynamic settings, string name) { if (settings is ExpandoObject) return ((IDictionary<string, object>)settings).ContainsKey(name); return settings.GetType().GetProperty(name) != null; } var settings = new {Filename = @"c:\temp\q.txt"}; Console.WriteLine(DoesPropertyExist(settings, "Filename")); Console.WriteLine(DoesPropertyExist(settings, "Size"));
产出:
True False
public static bool HasProperty(dynamic obj, string name) { Type objType = obj.GetType(); if (objType == typeof(ExpandoObject)) { return ((IDictionary<string, object>)obj).ContainsKey(name); } return objType.GetProperty(name) != null; }
这对我很有效:
public static bool IsPropertyExist(dynamic dynamicObj, string property) { try { var value=dynamicObj[property].Value; return true; } catch (RuntimeBinderException) { return false; } }
使用反射,这是我使用的函数:
public static bool doesPropertyExist(dynamic obj, string property) { return ((Type)obj.GetType()).GetProperties().Where(p => p.Name.Equals(property)).Any(); }
然后。
if (doesPropertyExist(myDynamicObject, "myProperty")){ // ... }
上面的解决方案都不适用于来自 Json的 dynamic,但是我设法用 Try catch(by@user3359453)通过改变抛出的异常类型(KeyNotFoundException而不是 RuntimeBinderException)将其转换成实际可行的..。
Json
dynamic
Try catch
KeyNotFoundException
RuntimeBinderException
public static bool HasProperty(dynamic obj, string name) { try { var value = obj[name]; return true; } catch (KeyNotFoundException) { return false; } }
希望这能为你节省点时间。
合并和修复来自 Serj-TM 和 user3359453的答案,以便它可以同时使用 ExpendoObject 和 DynamicJsonObject。这对我有用。
public static bool HasPropertyExist(dynamic settings, string name) { if (settings is System.Dynamic.ExpandoObject) return ((IDictionary<string, object>)settings).ContainsKey(name); if (settings is System.Web.Helpers.DynamicJsonObject) try { return settings[name] != null; } catch (KeyNotFoundException) { return false; } return settings.GetType().GetProperty(name) != null; }
这适用于匿名类型,ExpandoObject、 Nancy.DynamicDictionary或任何其他可以转换为 IDictionary<string, object>的类型。
ExpandoObject
Nancy.DynamicDictionary
IDictionary<string, object>
public static bool PropertyExists(dynamic obj, string name) { if (obj == null) return false; if (obj is IDictionary<string, object> dict) { return dict.ContainsKey(name); } return obj.GetType().GetProperty(name) != null; }
如果有人需要处理来自 Json 的动态对象,我已经修改了 Seth Reno answer 来处理从 Newton Soft 反序列化的动态对象。Jason JObject.
public static bool PropertyExists(dynamic obj, string name) { if (obj == null) return false; if (obj is ExpandoObject) return ((IDictionary<string, object>)obj).ContainsKey(name); if (obj is IDictionary<string, object> dict1) return dict1.ContainsKey(name); if (obj is IDictionary<string, JToken> dict2) return dict2.ContainsKey(name); return obj.GetType().GetProperty(name) != null; }
要扩展@Kuroro 的答案,如果您需要测试属性是否为空,那么下面的方法应该可以。
public static bool PropertyExistsAndIsNotNull(dynamic obj, string name) { if (obj == null) return false; if (obj is ExpandoObject) { if (((IDictionary<string, object>)obj).ContainsKey(name)) return ((IDictionary<string, object>)obj)[name] != null; return false; } if (obj is IDictionary<string, object> dict1) { if (dict1.ContainsKey(name)) return dict1[name] != null; return false; } if (obj is IDictionary<string, JToken> dict2) { if (dict2.ContainsKey(name)) return (dict2[name].Type != JTokenType.Null && dict2[name].Type != JTokenType.Undefined); return false; } if (obj.GetType().GetProperty(name) != null) return obj.GetType().GetProperty(name).GetValue(obj) != null; return false; }
这也适用于 DynamicJsonObject:
public static bool PropertyExists(dynamic settings, string name) { if (settings is ExpandoObject) return ((IDictionary<string, object>)settings).ContainsKey(name); else if (settings is DynamicJsonObject) return ((DynamicJsonObject)settings).GetDynamicMemberNames().Contains(name); return settings.GetType().GetProperty(name) != null; }
public static void Test() { int LOOP_LENGTH = 100000000; { long first_memory = GC.GetTotalMemory(true); var stopWatch = Stopwatch.StartNew(); Console.WriteLine("doesPropertyExist"); dynamic testdo = new { A = 1, B = (string)null, C = "A" }; for (int i = 0; i < LOOP_LENGTH; i++) { if (!TestDynamic.doesPropertyExist(testdo, "A")) { Console.WriteLine("throw find"); break; } if (TestDynamic.doesPropertyExist(testdo, "ABC")) { Console.WriteLine("throw not find"); break; } } stopWatch.Stop(); var last_memory = GC.GetTotalMemory(true); Console.WriteLine($" Time:{stopWatch.Elapsed.TotalSeconds}s\t Memory:{last_memory - first_memory}"); } { long first_memory = GC.GetTotalMemory(true); var stopWatch = Stopwatch.StartNew(); Console.WriteLine("HasProperty"); dynamic testdo = new { A = 1, B = (string)null, C = "A" }; for (int i = 0; i < LOOP_LENGTH; i++) { if (!TestDynamic.HasProperty(testdo, "A")) { Console.WriteLine("throw find"); break; } if (TestDynamic.HasProperty(testdo, "ABC")) { Console.WriteLine("throw not find"); break; } } stopWatch.Stop(); var last_memory = GC.GetTotalMemory(true); Console.WriteLine($" Time:{stopWatch.Elapsed.TotalSeconds}s\t Memory:{last_memory - first_memory}"); } { long first_memory = GC.GetTotalMemory(true); var stopWatch = Stopwatch.StartNew(); Console.WriteLine("IsPropertyExist"); dynamic testdo = new { A = 1, B = (string)null, C = "A" }; for (int i = 0; i < LOOP_LENGTH; i++) { if (!TestDynamic.IsPropertyExist(testdo, "A")) { Console.WriteLine("throw find"); break; } if (TestDynamic.IsPropertyExist(testdo, "ABC")) { Console.WriteLine("throw not find"); break; } } stopWatch.Stop(); var last_memory = GC.GetTotalMemory(true); Console.WriteLine($" Time:{stopWatch.Elapsed.TotalSeconds}s\t Memory:{last_memory - first_memory}"); } { long first_memory = GC.GetTotalMemory(true); var stopWatch = Stopwatch.StartNew(); Console.WriteLine("IsPropertyExistBinderException"); dynamic testdo = new { A = 1, B = (string)null, C = "A" }; for (int i = 0; i < LOOP_LENGTH; i++) { if (!TestDynamic.IsPropertyExistBinderException(testdo, "A")) { Console.WriteLine("throw find"); break; } if (TestDynamic.IsPropertyExistBinderException(testdo, "ABC")) { Console.WriteLine("throw not find"); break; } } stopWatch.Stop(); var last_memory = GC.GetTotalMemory(true); Console.WriteLine($" Time:{stopWatch.Elapsed.TotalSeconds}s\t Memory:{last_memory - first_memory}"); } { long first_memory = GC.GetTotalMemory(true); var stopWatch = Stopwatch.StartNew(); Console.WriteLine("PropertyExists"); dynamic testdo = new { A = 1, B = (string)null, C = "A" }; for (int i = 0; i < LOOP_LENGTH; i++) { if (!TestDynamic.PropertyExists(testdo, "A")) { Console.WriteLine("throw find"); break; } if (TestDynamic.PropertyExists(testdo, "ABC")) { Console.WriteLine("throw not find"); break; } } stopWatch.Stop(); var last_memory = GC.GetTotalMemory(true); Console.WriteLine($" Time:{stopWatch.Elapsed.TotalSeconds}s\t Memory:{last_memory - first_memory}"); } { long first_memory = GC.GetTotalMemory(true); var stopWatch = Stopwatch.StartNew(); Console.WriteLine("PropertyExistsJToken"); dynamic testdo = new { A = 1, B = (string)null, C = "A" }; for (int i = 0; i < LOOP_LENGTH; i++) { if (!TestDynamic.PropertyExistsJToken(testdo, "A")) { Console.WriteLine("throw find"); break; } if (TestDynamic.PropertyExistsJToken(testdo, "ABC")) { Console.WriteLine("throw not find"); break; } } stopWatch.Stop(); var last_memory = GC.GetTotalMemory(true); Console.WriteLine($" Time:{stopWatch.Elapsed.TotalSeconds}s\t Memory:{last_memory - first_memory}"); } } public static bool IsPropertyExist(dynamic settings, string name) { if (settings is ExpandoObject) return ((IDictionary<string, object>)settings).ContainsKey(name); return settings.GetType().GetProperty(name) != null; } public static bool HasProperty(dynamic obj, string name) { Type objType = obj.GetType(); if (objType == typeof(ExpandoObject)) { return ((IDictionary<string, object>)obj).ContainsKey(name); } return objType.GetProperty(name) != null; } public static bool PropertyExists(dynamic obj, string name) { if (obj == null) return false; if (obj is IDictionary<string, object> dict) { return dict.ContainsKey(name); } return obj.GetType().GetProperty(name) != null; } // public static bool HasPropertyExist(dynamic settings, string name) // { // if (settings is System.Dynamic.ExpandoObject) // return ((IDictionary<string, object>)settings).ContainsKey(name); // if (settings is DynamicJsonObject) // try // { // return settings[name] != null; // } // catch (KeyNotFoundException) // { // return false; // } // return settings.GetType().GetProperty(name) != null; // } public static bool IsPropertyExistBinderException(dynamic dynamicObj, string property) { try { var value = dynamicObj[property].Value; return true; } catch (RuntimeBinderException) { return false; } } public static bool HasPropertyFoundException(dynamic obj, string name) { try { var value = obj[name]; return true; } catch (KeyNotFoundException) { return false; } } public static bool doesPropertyExist(dynamic obj, string property) { return ((Type)obj.GetType()).GetProperties().Where(p => p.Name.Equals(property)).Any(); } public static bool PropertyExistsJToken(dynamic obj, string name) { if (obj == null) return false; if (obj is ExpandoObject) return ((IDictionary<string, object>)obj).ContainsKey(name); if (obj is IDictionary<string, object> dict1) return dict1.ContainsKey(name); if (obj is IDictionary<string, JToken> dict2) return dict2.ContainsKey(name); return obj.GetType().GetProperty(name) != null; } // public static bool PropertyExistsJsonObject(dynamic settings, string name) // { // if (settings is ExpandoObject) // return ((IDictionary<string, object>)settings).ContainsKey(name); // else if (settings is DynamicJsonObject) // return ((DynamicJsonObject)settings).GetDynamicMemberNames().Contains(name); // return settings.GetType().GetProperty(name) != null; // } }
DoesPropertyExist
时间: 59.5907507 s 内存: 403680
HasProperty
时间: 30.8231781 s 内存: 14968
IsPropertyExist
时间: 39.6179575 s 内存: 97000
抛出查找
Property 存在
时间: 56.009761 s 内存: 13464
Property 存在 JToken
时间: 61.6146953 s 内存: 15952
我碰到的动态是 Newtonsoft.Json.Linq.JObject而不是 IDictionary
Newtonsoft.Json.Linq.JObject
IDictionary
我添加了额外的如果,它工作。
public static bool PropertyExists(dynamic obj, string name) { if (obj == null) return false; else if (obj is IDictionary<string, object> dict) { return dict.ContainsKey(name); } else if (obj is Newtonsoft.Json.Linq.JObject jObject) { return jObject.ContainsKey(name); } else { return obj.GetType().GetProperty(name) != null; } }
使用 switch 表达式编辑 智能解决方案
public static bool PropertyExists(dynamic obj, string name) { if (obj == null) return false; return obj switch { IDictionary<string, object> dict => dict.ContainsKey(name), Newtonsoft.Json.Linq.JObject jObject => jObject.ContainsKey(name), _ => obj.GetType().GetProperty(name) != null }; }
为了节省其他人的时间,这个答案涵盖了很多使用 Newtonstoft Json 动态反序列化来搜索这个问题的人:
dynamic dynamicObject = JsonConvert.DeserializeObject<dynamic>(json); if (IsContainsKey(dynamicObject, "searchText")) searchText = dynamicObject.searchText; bool IsContainsKey(dynamic newtonsoftDynamic, string propertyName) { return (newtonsoftDynamic as JObject).ContainsKey(propertyName); }
或者只是代码:
JObject obj = dynamicObject as JObject; string searchText = string.Empty; if (obj.ContainsKey("searchText")) searchText = obj.Value<string>("searchText");
没有例外,通过 Newtonsoft 进行适当的处理,但你仍可以使用 dynamicobject.xxx ,因为你知道这些房产永远都会在那里。