ฉันจะตรวจสอบได้อย่างไรว่าคุณสมบัติมีอยู่ในประเภทที่ไม่ระบุตัวตนแบบไดนามิกใน c #


122

ฉันมีอ็อบเจ็กต์ประเภทไม่ระบุตัวตนที่ฉันได้รับเป็นไดนามิกจากวิธีการที่ฉันต้องการตรวจสอบคุณสมบัติที่มีอยู่ในอ็อบเจ็กต์นั้น

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

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

ฉันจะใช้ IsSettingExist ได้อย่างไร



หากคุณพบว่าตัวเองต้องพึ่งพาวัตถุแบบไดนามิกอย่างมากมันอาจจะคุ้มค่าที่จะมองไปที่ F # - Nice Avatar โดยวิธี
Piotr Kula

คำตอบ:


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
Ian Kemp

@ Gaspa79 เป็นรูปแบบการเข้ารหัสที่ไม่ใช่เรื่องแปลก บางคนชอบคำนำหน้า "Is" ในคุณสมบัติบูลีนทั้งหมด ความสม่ำเสมอเช่นนี้สามารถป้องกันไม่ให้คุณต้องเดาอักขระสองสามตัวแรกของตัวระบุ (หลังจากนั้น Intellisense ใช้งานได้) แต่ต้องเสียค่าใช้จ่ายในการสร้างภาษาอังกฤษที่น่าอึดอัดเล็กน้อยในกรณีเช่นนี้
solublefish

ผมพบว่าไม่ถูกต้องคำกริยาตึงเครียดของคำนำหน้าจะมีมากขึ้นทำให้เกิดความสับสนกว่ามันจะเป็นอย่างอื่นไปใช้Is HasPropertyฉันจะบอกด้วยว่าการใช้คำนำหน้าไม่ถูกต้องตามหลักไวยากรณ์เช่นนี้ไม่ใช่สำนวนในC♯
Ben Collins

ExpandoObject ไม่ใช่สิ่งเดียวกับประเภทที่ไม่ระบุตัวตน ฉันผิดเรื่องนั้นเหรอ?
ryanwebjackson

38
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;ส่งคืนค่าว่างในคุณสมบัติที่มีอยู่
Matas Vaitkevicius

3
objType.GetProperty(name) != nullจะส่งคืน a เสมอboolซึ่ง (ตามนิยาม) ไม่สามารถเป็นnullได้
Alex McMillan

@AlexMcMillan ไม่แน่ใจว่าคุณอาศัยอยู่ในมิติใดType.GetProperty(string)สำหรับคุณสมบัติที่ไม่มีอยู่จะส่งคืนสิ่งอื่นที่ไม่ใช่ null
Ian Kemp

2
@IanKemp, AlexMcMillan กล่าวว่าobjType.GetProperty (name)! = nullในการตอบกลับความคิดเห็น MatasVaitkevicius จริง
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.DynamicDictionaryIDictionary<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
ทางออกที่ดี ฉันต้องการเพิ่มคำสั่ง IF อีกหนึ่งคำสั่งเมื่อแปลงสตริง JSON เป็น JObject .... "if (obj คือ Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name); "
rr789

1
ยังทำงานให้ฉัน คำตอบที่ยอดเยี่ยม Seth Reno ฉันได้เพิ่ม "if (obj คือ Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (ชื่อ);" ในฟังก์ชันข้างต้นตามที่แนะนำโดย 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

ล้มเหลวด้วยRuntimeBinderExceptionและdynamicObj[property].Value เมื่อค่าเป็นจริงมี ... var value = dynamicObj[property]เป็นพอ ... และเมื่อมันไม่ได้อยู่KeyNotFoundException ในการDictionaryถูกโยน ... ดูด้านล่าง ...
Matas 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

การรวมและแก้ไขคำตอบจาก 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;
}

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

1

ในกรณีที่มีคนต้องการจัดการวัตถุแบบไดนามิกที่มาจาก Json ฉันได้แก้ไขคำตอบของ Seth Reno เพื่อจัดการกับวัตถุแบบไดนามิกที่ถูก deserialized จาก 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;
    }

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.