简体   繁体   English

c# - 如何检查属性是否存在于c#中的动态匿名类型?

[英]How do I check if a property exists on a dynamic anonymous type in c#?

I have an anonymous type object that I receive as a dynamic from a method I would like to check in a property exists on that object.我有一个匿名类型对象,我从我想检查该对象上存在的属性的方法中作为动态接收。

....
var settings = new {
                   Filename="temp.txt",
                   Size=10
}
...

function void Settings(dynamic settings) {
var exists = IsSettingExist(settings,"Filename")
}

How would I implement IsSettingExist ?我将如何实现 IsSettingExist ?

  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;
  }

  var settings = new {Filename = @"c:\temp\q.txt"};
  Console.WriteLine(IsPropertyExist(settings, "Filename"));
  Console.WriteLine(IsPropertyExist(settings, "Size"));

Output:输出:

 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;
}

if you can control creating/passing the settings object, i'd recommend using an ExpandoObject instead.如果您可以控制创建/传递设置对象,我建议您改用 ExpandoObject。

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 ....
}

This works for anonymous types, ExpandoObject , Nancy.DynamicDictionary or anything else that can be cast to IDictionary<string, object> .这适用于匿名类型、 ExpandoObjectNancy.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;
    }

Merging and fixing answers from Serj-TM and user3359453 so that it works with both ExpandoObject and DynamicJsonObject.合并和修复来自 Serj-TM 和 user3359453 的答案,以便它同时适用于 ExpandoObject 和 DynamicJsonObject。 This works for me.这对我有用。

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;
}

This is working for me-:这对我有用-:

  public static bool IsPropertyExist(dynamic dynamicObj, string property)
       {
           try
           {
               var value=dynamicObj[property].Value;
               return true;
           }
           catch (RuntimeBinderException)
           {

               return false;
           }

       }

Using reflection, this is the function i use :使用反射,这是我使用的功能:

public static bool doesPropertyExist(dynamic obj, string property)
{
    return ((Type)obj.GetType()).GetProperties().Where(p => p.Name.Equals(property)).Any();
}

then..然后..

if (doesPropertyExist(myDynamicObject, "myProperty")){
    // ...
}

None of the solutions above worked for dynamic that comes from Json , I however managed to transform one with Try catch (by @user3359453) by changing exception type thrown ( KeyNotFoundException instead of RuntimeBinderException ) into something that actually works...上面的解决方案都不适用于来自Json dynamic ,但是我设法通过将抛出的异常类型( KeyNotFoundException而不是RuntimeBinderException )更改为实际工作的东西来使用Try catch (由@user3359453 提供)转换一个...

public static bool HasProperty(dynamic obj, string name)
    {
        try
        {
            var value = obj[name];
            return true;
        }
        catch (KeyNotFoundException)
        {
            return false;
        }
    }

在此处输入图片说明

Hope this saves you some time.希望这可以为您节省一些时间。

In case someone need to handle a dynamic object come from Json, I has modified Seth Reno answer to handle dynamic object deserialized from NewtonSoft.Json.JObjcet.如果有人需要处理来自 Json 的动态对象,我已修改 Seth Reno 答案以处理从 NewtonSoft.Json.JObjcet 反序列化的动态对象。

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;
    }

I ran into the dynamic was Newtonsoft.Json.Linq.JObject instead of IDictionary我遇到的动态是Newtonsoft.Json.Linq.JObject而不是IDictionary

I added and extra if and it works.我添加了额外的如果它有效。

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;
    }
}

To extend the answer from @Kuroro, if you need to test if the property is empty, below should work.为了扩展@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;
}

I have an anonymous type object that I receive as a dynamic from a method I would like to check in a property exists on that object.我有一个匿名类型对象,该对象是我想检查的对象中存在的属性作为动态方法接收的。

....
var settings = new {
                   Filename="temp.txt",
                   Size=10
}
...

function void Settings(dynamic settings) {
var exists = IsSettingExist(settings,"Filename")
}

How would I implement IsSettingExist ?我将如何实现IsSettingExist?

This works also for DynamicJsonObject:这也适用于 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是否存在属性

Time:59.5907507s Memory:403680时间:59.5907507s 内存:403680

HasProperty有属性

Time:30.8231781s Memory:14968时间:30.8231781s 内存:14968

IsPropertyExist是否存在属性

Time:39.6179575s Memory:97000时间:39.6179575s 内存:97000

IsPropertyExistBinderException throw find IsPropertyExistBinderException 抛出 find

PropertyExists属性存在

Time:56.009761s Memory:13464时间:56.009761s 内存:13464

PropertyExistsJToken PropertyExistsJToken

Time:61.6146953s Memory:15952时间:61.6146953s 内存:15952

To save others some time and this answer covers a lot of the people Googling this question using Newtonstoft Json deserialization with dynamics:为了节省其他人的时间,这个答案涵盖了很多使用 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);
}

or just in code:或者只是在代码中:

JObject obj = dynamicObject as JObject;
string searchText = string.Empty;
if (obj.ContainsKey("searchText"))
    searchText = obj.Value<string>("searchText");

no exceptions, proper handling via Newtonsoft but you can still use the dynamicObject.xxx for properties you know will always be there.没有例外,通过 Newtonsoft 进行正确处理,但您仍然可以将 dynamicObject.xxx 用于您知道将始终存在的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM