Bagaimana cara memeriksa apakah properti ada pada tipe anonim dinamis di c #?


122

Saya memiliki tipe objek anonim yang saya terima sebagai dinamika dari metode yang saya ingin periksa di properti yang ada pada objek itu.

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

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

Bagaimana cara menerapkan IsSettingExist?



Jika Anda menemukan diri Anda sangat bergantung pada objek dinamis, mungkin ada baiknya melihat F # - Ngomong-ngomong, Avatar Bagus
Piotr Kula

Jawaban:


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

Keluaran:

 True
 False

3
Ini tidak bekerja pada objek dinamis. Itu selalu mengembalikan nol.
evilom

@evilom @Shikasta_Kashti Apakah Anda mencoba menggunakan metode ini dengan MVC ViewBag? Jika demikian, lihat stackoverflow.com/a/24192518/70345
Ian Kemp

@Bayu_joo. Ini adalah konvensi pengkodean yang tidak biasa. Beberapa orang menyukai awalan "Is" pada semua properti boolean. Konsistensi seperti itu dapat mencegah Anda dari keharusan menebak beberapa karakter pertama dari suatu pengenal (setelah itu, Intellisense berfungsi), tetapi dengan mengorbankan membuat bahasa Inggris menjadi sedikit canggung dalam kasus seperti ini.
solublefish

Saya menemukan bentuk kata kerja yang tidak valid dari Isawalan menjadi lebih membingungkan daripada yang akan digunakan HasProperty. Saya juga akan mengatakan bahwa menggunakan awalan yang salah secara tata bahasa seperti ini sebenarnya non-idiomatik di C♯.
Ben Collins

ExpandoObject tidak sama dengan tipe anonim. Apakah saya salah tentang itu?
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;mengembalikan null pada properti yang ada
Matas Vaitkevicius

3
objType.GetProperty(name) != nullakan selalu mengembalikan a bool, yang (menurut definisi) tidak akan pernah bisa null.
Alex McMillan

@AlexMcMillan Tidak yakin di dimensi apa Anda tinggal di mana Type.GetProperty(string)untuk properti yang tidak ada mengembalikan apa pun selain null.
Ian Kemp

2
@IanKemp, AlexMcMillan mengatakan objType.GetProperty (name)! = Null dalam membalas komentar MatasVaitkevicius sebenarnya.
Sergey

15

jika Anda dapat mengontrol pembuatan / penerusan objek pengaturan, saya akan merekomendasikan menggunakan ExpandoObject sebagai gantinya.

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

Saya tidak dapat mengubahnya, dapatkah saya mentransmisikan ke ExpendoObject?
David MZ

6

Ini berfungsi untuk jenis anonim ExpandoObject, Nancy.DynamicDictionaryatau apa pun yang dapat ditransmisikan 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
Solusi bagus. Saya perlu menambahkan satu lagi pernyataan IF saat mengubah string JSON menjadi JObject .... "if (obj adalah Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name); "
rr789

1
Juga bekerja untuk saya. Jawaban luar biasa Seth Reno. Saya juga menambahkan "if (obj adalah Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name);" dalam fungsi di atas seperti yang disarankan oleh rr789. Jadi, harap edit juga jawaban Anda untuk menyertakannya.
Brijesh Kumar Tripathi

1
Terima kasih @BrijeshKumarTripathi! Ini persis skenario saya.
ryanwebjackson

4

Ini bekerja untuk saya-:

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

               return false;
           }

       }

14
Membiarkan pengecualian terjadi dan kemudian menangkapnya bukanlah solusi yang disukai karena ada banyak overhead yang terkait dengan melempar dan menangkap. Ini hanya pilihan terakhir. Pengecualian dirancang untuk situasi yang seharusnya tidak terjadi selama eksekusi seperti jaringan yang tidak tersedia. Ada solusi yang jauh lebih baik di sini.
Apapun Man

Gagal dengan RuntimeBinderExceptiondan dynamicObj[property].Value ketika nilai sebenarnya ada ... var value = dynamicObj[property]cukup ... dan ketika itu tidak ada KeyNotFoundException di Dictionarydilemparkan ... lihat di bawah ...
Matas Vaitkevicius

Ini bukan solusi yang dapat diterima untuk menggunakan pengecualian dalam logika bisnis. 1 kelas, semester 2.
Artem G

3

Tak satu pun dari solusi di atas yang berfungsi untuk dynamicitu berasal dari Json, namun saya berhasil mengubahnya dengan Try catch(oleh @ user3359453) dengan mengubah jenis pengecualian yang dilemparkan ( KeyNotFoundExceptionbukan RuntimeBinderException) menjadi sesuatu yang benar-benar berfungsi ...

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

masukkan deskripsi gambar di sini

Semoga ini menghemat waktu Anda.


1
Menggunakan pengecualian untuk hal-hal seperti ini tidak disarankan. Seharusnya memilih sesuatu seperti casting ke JObject dan menggunakan .Property ()! = Null
Gaspa79

3

Menggabungkan dan memperbaiki jawaban dari Serj-TM dan user3359453 sehingga berfungsi dengan ExpandoObject dan DynamicJsonObject. Ini berhasil untuk saya.

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

Menggunakan refleksi, inilah fungsi yang saya gunakan:

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

kemudian..

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

2
GetProperties () tidak mencantumkan Anggota dinamis di DynamicObject. Ada fungsi GetDynamicMemberNames () khusus untuk itu.
Marco Guignard

Menggunakan ekspresi lambda Whereterlebih dahulu, kemudian Anyberlebihan, karena Anda juga dapat merumuskan ekspresi pemfilteran Any.
pholpar

1

Jika seseorang perlu menangani objek dinamis yang berasal dari Json, saya telah memodifikasi jawaban Seth Reno untuk menangani objek dinamis yang dideserialisasi dari 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

Untuk memperluas jawaban dari @Kuroro, jika Anda perlu menguji apakah propertinya kosong, di bawah ini akan berfungsi.

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;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.