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

Dav*_* MZ 112 c# reflection dynamic .net-4.0 c#-4.0

我有一个匿名类型对象,我从一个方法接收动态,我想检查该对象上存在的属性.

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

function void Settings(dynamic settings) {
var exists = IsSettingExist(settings,"Filename")
}
Run Code Online (Sandbox Code Playgroud)

我该如何实现IsSettingExist?

Ser*_*-Tm 128

  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"));
Run Code Online (Sandbox Code Playgroud)

输出:

 True
 False
Run Code Online (Sandbox Code Playgroud)

  • 这并不适用于所有情况:http://stackoverflow.com/a/11540889/238419 (12认同)
  • 这不适用于动态对象。它总是返回空值。 (6认同)
  • 真正的问题:为什么IsPropertyExist而不是DoesPropertyExist/HasProperty?这是一个我不明白的惯例吗? (3认同)
  • 我发现“Is”前缀的无效动词时态比使用“HasProperty”更令人困惑。我还想说,使用像这样的语法不正确的前缀实际上在 C♯ 中是不惯用的。 (3认同)

Ser*_*gey 34

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;
}
Run Code Online (Sandbox Code Playgroud)

  • `objType.GetProperty(name)!= null`将始终返回一个`bool`,(根据定义)不能是`null`. (3认同)
  • @IanKemp,AlexMcMillan说**objType.GetProperty(名字)!= null**实际上回复了MatasVaitkevicius的评论. (2认同)

Mik*_*ran 13

如果你可以控制创建/传递设置对象,我建议使用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 ....
}
Run Code Online (Sandbox Code Playgroud)


Set*_*eno 12

这适用于匿名类型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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案。在将 JSON 字符串转换为 JObject 时,我需要再添加一个 IF 语句......"if (obj is Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject)obj).ContainsKey(name); ” (2认同)

Osc*_*nez 10

我遇到的动态是Newtonsoft.Json.Linq.JObject而不是IDictionary

我添加了额外的 if 并且它有效。

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用 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
    };
}
Run Code Online (Sandbox Code Playgroud)


Kur*_*oro 7

如果有人需要处理来自 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;
    }
Run Code Online (Sandbox Code Playgroud)


Bru*_*tta 5

合并并修复 Serj-TM 和 user3359453 的答案,以便它可以与 ExpandoObject 和 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;
}
Run Code Online (Sandbox Code Playgroud)