Bir özelliğin c # 'de dinamik anonim türde olup olmadığını nasıl kontrol ederim?


122

Bir yöntemden dinamik olarak aldığım anonim bir tür nesnem var, bu nesnede bir özelliğin var olduğunu kontrol etmek istediğim.

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

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

IsSettingExist'i nasıl uygularım?



Kendinizi dinamik nesnelere fazlasıyla bağlı bulursanız, muhtemelen F # - Güzel
Piotr Kula

Yanıtlar:


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

Çıktı:

 True
 False

3
Bu, dinamik nesnelerde çalışmaz. Her zaman boş döndürür.
evilom

@evilom @Shikasta_Kashti Bu yöntemi bir MVC ile kullanmaya mı çalışıyorsunuz ViewBag? Öyleyse, stackoverflow.com/a/24192518/70345 sayfasına
Ian Kemp

Gaspa79 @. Bu alışılmadık bir kodlama kuralı. Bazıları tüm boole özelliklerinde "Is" ön eki ister. Böyle bir tutarlılık, bir tanımlayıcının ilk birkaç karakterini tahmin etmek zorunda kalmanızı engelleyebilir (bundan sonra Intellisense çalışır), ancak bu gibi durumlarda biraz garip İngilizce yapma pahasına.
solublefish

IsÖnekin geçersiz fiil zamanını başka türlü kullanmaktan daha kafa karıştırıcı buluyorum HasProperty. Ayrıca bunun gibi dilbilgisi açısından yanlış bir önek kullanmanın aslında C♯'da deyimsel olmadığını da söyleyebilirim.
Ben Collins

ExpandoObject anonim tür ile aynı şey değildir. Bu konuda yanılıyor muyum?
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;var olan özelliklerde null döndürür
Matas Vaitkevicius

3
objType.GetProperty(name) != nullher zaman bool(tanım gereği) hiçbir zaman olamayacak olan a döndürür null.
Alex McMillan

@AlexMcMillan Type.GetProperty(string)Varolmayan bir mülk için hangi boyutta yaşadığınızdan emin değilsiniz.
Ian Kemp

2
@IanKemp, AlexMcMillan MatasVaitkevicius yorumuna cevaben objType.GetProperty (name)! = Null dedi .
Sergey

15

ayarlar nesnesini oluşturmayı / iletmeyi kontrol edebiliyorsanız, bunun yerine bir ExpandoObject kullanmanızı tavsiye ederim.

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

Değiştiremiyorum, ExpendoObject'e aktarabilir miyim?
David MZ

6

Anonim türleri için bu eserler ExpandoObject, Nancy.DynamicDictionaryhiç dökülebilir başka ya da bir şey 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
Harika çözüm. JSON dizesini JObject .... 'e dönüştürürken bir tane daha IF ifadesi eklemem gerekiyordu "if (obj is Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name); "
rr789

1
Benim için de çalıştı. Harika cevap Seth Reno. Ayrıca "if (obj is Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (name);" rr789 tarafından önerildiği gibi yukarıdaki işlevde. Bu nedenle, lütfen yanıtınızı içerecek şekilde düzenleyin.
Brijesh Kumar Tripathi

1
Teşekkür ederim @BrijeshKumarTripathi! Bu tam olarak benim senaryomdu.
ryanwebjackson

4

Bu benim için çalışıyor-:

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

               return false;
           }

       }

14
İstisnaların oluşmasına izin vermek ve sonra onları yakalamak tercih edilen bir çözüm değildir çünkü fırlatma ve yakalama ile ilgili çok fazla ek yük vardır. Bu sadece son çare. İstisnalar, bir ağın kullanılamaz olması gibi yürütme sırasında olmaması gereken durumlar için tasarlanmıştır . Burada çok daha iyi çözümler var.
Whatever Man

Başarısız olur RuntimeBinderExceptionve dynamicObj[property].Value değer gerçekten oradaysa ... var value = dynamicObj[property]yeterlidir ... ve KeyNotFoundException üzerinde olmadığı zaman Dictionaryfırlatılır ... aşağıya bakın ...
Matas Vaitkevicius

İş mantığında istisnaların kullanılması kabul edilebilir bir çözüm değildir. 1. sınıf, 2. dönem.
Artem G

3

İçin çalışmış Yukarıdaki çözümlerin hiçbiri dynamicbu geliyor Jsonben ancak olanı dönüştürmeyi başardığını, Try catch(atılan istisna tipini değiştirerek (@ user3359453 tarafından) KeyNotFoundExceptionyerine RuntimeBinderExceptiono gerçekten çalışıyor şeye) ...

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

görüntü açıklamasını buraya girin

Umarım bu size biraz zaman kazandırır.


1
Bunun gibi şeyler için istisnaların kullanılması tavsiye edilmez. JObject'e döküm yapmak ve .Property ()! = Null kullanmak gibi bir şeye gitmeliydim
Gaspa79

3

Serj-TM ve user3359453'ten gelen yanıtları hem ExpandoObject hem de DynamicJsonObject ile çalışacak şekilde birleştirip düzeltiyor. Bu benim için çalışıyor.

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

Yansımayı kullanarak kullandığım işlev bu:

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

sonra..

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

2
GetProperties (), DynamicObject'te dinamik Üyeyi listelemez. Bunun için özel bir GetDynamicMemberNames () işlevi vardır.
Marco Guignard

Filtreleme ifadenizi de formüle edebileceğiniz için, Whereönce lambda ifadesini kullanmak ve sonra Anygereksizdir Any.
pholpar

1

Birinin Json'dan gelen dinamik bir nesneyi işlemesi gerektiğinde, NewtonSoft.Json.JObjcet'ten gelen dinamik nesneyi işlemek için Seth Reno yanıtını değiştirdim.

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

Cevabı @Kuroro'dan uzatmak için, mülkün boş olup olmadığını test etmeniz gerekiyorsa, aşağıdaki çalışmalıdır.

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.