C #의 동적 익명 형식에 속성이 있는지 어떻게 확인합니까?


122

해당 개체에 속성이 있는지 확인하려는 메서드에서 동적으로받는 익명 형식 개체가 있습니다.

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

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

IsSettingExist를 어떻게 구현합니까?



그런데 멋진 아바타 - 당신이 당신 자신을 발견하면 크게 동적에 의존하는 것은 F 번호보고는 아마 가치가 객체
피오트르 쿨라

답변:


150
  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"));

산출:

 True
 False

3
이것은 동적 개체에서 작동하지 않습니다. 항상 null을 반환합니다.
evilom

@evilom @Shikasta_Kashti MVC에서이 방법을 사용하려고 ViewBag합니까? 이 경우, 참조 stackoverflow.com/a/24192518/70345
이안 켐프

@ Gaspa79. 드물지 않은 코딩 규칙입니다. 어떤 사람들은 모든 부울 속성에 "Is"접두사를 좋아합니다. 이와 같은 일관성은 식별자의 처음 몇 글자를 추측 할 필요가 없게 할 수 있지만 (이후 Intellisense가 작동 함) 이와 같은 경우 약간 어색한 영어를 만드는 대신 비용이 발생합니다.
solutionfish

Is접두사 의 유효하지 않은 동사 시제는 다른 방법으로 사용하는 것보다 더 혼란 스럽습니다 HasProperty. 나는 또한 이와 같이 문법적으로 잘못된 접두사를 사용하는 것은 실제로 C♯에서 비 관용적이라고 말할 수 있습니다.
Ben Collins

ExpandoObject는 익명 유형과 동일하지 않습니다. 내가 틀렸나 요?
ryanwebjackson

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

objType.GetProperty(name) != null;반환이 존재 할 특성에 널 (null)
마타스 Vaitkevicius

3
objType.GetProperty(name) != null항상을 반환하며 bool, (정의에 따라) 결코 null.
Alex McMillan

@AlexMcMillan Type.GetProperty(string)존재하지 않는 속성에 대해 어떤 차원에 살고 있는지 확실 하지 않아 null 이외의 항목이 반환됩니다.
Ian Kemp

2
@IanKemp, AlexMcMillan은 실제로 MatasVaitkevicius 주석에 대한 응답으로 objType.GetProperty (name)! = null 이라고 말했습니다 .
Sergey

15

설정 개체 만들기 / 전달을 제어 할 수 있다면 대신 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 ....
}

변경할 수 없습니다. ExpendoObject로 캐스트 할 수 있습니까?
David MZ

6

익명 형식에 대해이 작품 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;
    }

2
훌륭한 솔루션입니다. JSON 문자열을 JObject로 변환 할 때 IF 문을 하나 더 추가해야합니다 .... "if (obj는 Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name); "
rr789

1
또한 나를 위해 일했습니다. 멋진 대답 Seth Reno. 또한 "if (obj is Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name);"을 추가했습니다. " rr789가 제안한 위의 기능에서. 따라서 답변을 수정하여 포함 시키십시오.
Brijesh Kumar Tripathi

1
@BrijeshKumarTripathi 감사합니다! 이것이 바로 제 시나리오였습니다.
ryanwebjackson

4

이것은 나를 위해 일하고 있습니다-:

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

               return false;
           }

       }

14
예외 발생을 허용 한 다음 포착하는 것은 던지고 포착하는 것과 관련된 많은 오버 헤드가 있기 때문에 선호되는 솔루션이 아닙니다. 마지막 수단 일뿐입니다. 예외는 네트워크를 사용할 수없는 것과 같이 실행 과정에서 발생하지 않아야 하는 상황을 위해 설계되었습니다 . 여기에 훨씬 더 나은 솔루션이 있습니다.
Whatever Man

실패 RuntimeBinderExceptiondynamicObj[property].Value 값이 실제로있을 때 ... var value = dynamicObj[property]충분히 ... 그리고 존재하지 않는 경우 KeyNotFoundException Dictionary발생합니다 ... 아래 참조
마타스 Vaitkevicius

비즈니스 로직에서 예외를 사용하는 것은 허용 가능한 솔루션이 아닙니다. 1 학년, 2 학기.
Artem G

3

근무 위의 솔루션 중 어느 것도 dynamic그에서 온다 Json나는 그러나 하나의 변형 관리, Try catch(던져 예외 유형 변경 (@ user3359453에 의해)을 KeyNotFoundException대신 RuntimeBinderException하는 것이 실제로 작동 뭔가를) ...

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

여기에 이미지 설명 입력

이것이 시간을 절약하기를 바랍니다.


1
이와 같은 것에 예외를 사용하는 것은 권장되지 않습니다. !하는 jobject에 캐스팅 및 .Property ()를 사용하여 같은 뭔가 갔어요해야 = NULL
Gaspa79

3

ExpandoObject 및 DynamicJsonObject 모두에서 작동하도록 Serj-TM 및 user3359453의 답변을 병합하고 수정합니다. 이것은 나를 위해 작동합니다.

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

2

리플렉션을 사용하면 이것이 내가 사용하는 기능입니다.

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

그때..

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

2
GetProperties ()는 DynamicObject의 동적 멤버를 나열하지 않습니다. 이를위한 전용 함수 GetDynamicMemberNames ()가 있습니다.
Marco Guignard

Where먼저 람다 식을 사용한 다음 Any필터링 식을 공식화 할 수 있으므로 중복 Any됩니다.
pholpar 2019-08-20

1

누군가가 Json에서 온 동적 객체를 처리해야하는 경우 NewtonSoft.Json.JObjcet에서 역 직렬화 된 동적 객체를 처리하도록 Seth Reno 응답을 수정했습니다.

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

0

@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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.