Làm cách nào để kiểm tra xem thuộc tính có tồn tại kiểu ẩn danh động trong c # hay không?


122

Tôi có một đối tượng kiểu ẩn danh mà tôi nhận được dưới dạng động từ một phương thức mà tôi muốn kiểm tra trong thuộc tính tồn tại trên đối tượng đó.

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

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

Làm cách nào để triển khai IsSettingExist?



Nếu bạn tìm thấy tự của bạn phụ thuộc nhiều vào động vật có lẽ nó đáng được xem xét F # - Nice Avatar bằng cách này
Piotr Kula

Câu trả lời:


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

Đầu ra:

 True
 False

3
Điều này không hoạt động trên các đối tượng động. Nó luôn trả về null.
evilom

@evilom @Shikasta_Kashti Bạn đang cố gắng sử dụng phương pháp này với MVC ViewBag? Nếu vậy, hãy xem stackoverflow.com/a/24192518/70345
Ian Kemp,

@ Gaspa79. Đó là một quy ước mã hóa không phổ biến. Một số người thích tiền tố "Là" trên tất cả các thuộc tính boolean. Sự nhất quán như vậy có thể giúp bạn không phải đoán một vài ký tự đầu tiên của một số nhận dạng (sau đó, Intellisense hoạt động), nhưng bạn phải làm một chút tiếng Anh vụng về trong những trường hợp như thế này.
cá hòa tan

Tôi thấy thì động từ không hợp lệ của Istiền tố sẽ gây nhầm lẫn hơn so với cách sử dụng khác HasProperty. Tôi cũng sẽ nói rằng việc sử dụng một tiền tố sai ngữ pháp như thế này thực sự không phải là thành ngữ trong C♯.
Ben Collins

ExpandoObject không giống với kiểu ẩn danh. Tôi có sai về điều đó không?
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;trả về null trên tài sản mà làm tồn tại
Matas Vaitkevicius

3
objType.GetProperty(name) != nullsẽ luôn trả về a bool, mà (theo định nghĩa) không bao giờ được null.
Alex McMillan,

@AlexMcMillan Không chắc bạn đang sống ở thứ nguyên nào trong đó Type.GetProperty(string)đối với một thuộc tính không tồn tại trả về bất kỳ thứ gì khác ngoài null.
Ian Kemp

2
@IanKemp, AlexMcMillan cho biết objType.GetProperty (name)! = Null để trả lời thực tế nhận xét của MatasVaitkevicius.
Sergey

15

nếu bạn có thể kiểm soát việc tạo / chuyển đối tượng cài đặt, tôi khuyên bạn nên sử dụng ExpandoObject để thay thế.

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

Tôi không thể thay đổi nó, tôi có thể truyền sang ExpendoObject không?
David MZ,

6

Này hoạt động với nhiều loại mang tính chất ExpandoObject, Nancy.DynamicDictionaryhoặc bất cứ điều gì khác mà có thể được ép 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
Giải pháp tuyệt vời. Tôi cần thêm một câu lệnh IF nữa khi chuyển đổi chuỗi JSON thành JObject .... "if (obj là Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (tên); "
rr789

1
Cũng làm việc cho tôi. Câu trả lời tuyệt vời Seth Reno. Tôi cũng đã thêm "if (obj là Newtonsoft.Json.Linq.JObject) return ((Newtonsoft.Json.Linq.JObject) obj) .ContainsKey (tên);" trong chức năng trên theo gợi ý của rr789. Vì vậy, hãy cũng chỉnh sửa câu trả lời của bạn để bao gồm nó.
Brijesh Kumar Tripathi

1
Cảm ơn bạn @BrijeshKumarTripathi! Đây chính xác là kịch bản của tôi.
ryanwebjackson

4

Điều này đang làm việc cho tôi-:

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

               return false;
           }

       }

14
Để các trường hợp ngoại lệ xảy ra và sau đó bắt chúng không phải là giải pháp được ưa thích vì có rất nhiều chi phí liên quan đến việc ném và bắt. Đó là phương sách cuối cùng duy nhất. Các trường hợp ngoại lệ được thiết kế cho các tình huống không nên xảy ra trong quá trình thực thi như mạng không khả dụng. Có nhiều giải pháp tốt hơn ở đây.
Dù Man

Không thành công với RuntimeBinderExceptiondynamicObj[property].Value khi giá trị thực sự ở đó ... var value = dynamicObj[property]là đủ ... và khi nó không tồn tại KeyNotFoundException trên Dictionaryđược ném ... xem dưới đây ...
Matas Vaitkevicius

Không thể chấp nhận giải pháp sử dụng ngoại lệ trong logic kinh doanh. 1 lớp, học kỳ 2.
Artem G

3

Không có giải pháp nào ở trên hoạt động cho dynamicđiều đó Json, tuy nhiên, tôi đã quản lý để chuyển đổi một giải pháp với Try catch(bởi @ user3359453) bằng cách thay đổi loại ngoại lệ được ném ( KeyNotFoundExceptionthay vì RuntimeBinderException) thành thứ thực sự hoạt động ...

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

nhập mô tả hình ảnh ở đây

Hy vọng điều này giúp bạn tiết kiệm thời gian.


1
Sử dụng ngoại lệ cho những thứ như thế này không được khuyến khích. ! Nên đã đi một cái gì đó giống như đúc để JObject và sử dụng .Property () = null
Gaspa79

3

Hợp nhất và sửa các câu trả lời từ Serj-TM và user3359453 để nó hoạt động với cả ExpandoObject và DynamicJsonObject. Điều này làm việc cho tôi.

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

Sử dụng phản chiếu, đây là chức năng tôi sử dụng:

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

sau đó..

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

2
GetProperties () không liệt kê Thành viên động trên DynamicObject. Có một hàm riêng GetDynamicMemberNames () cho việc đó.
Marco Guignard

Sử dụng biểu thức lambda Wheretrước và sau đó Anylà dư thừa, vì bạn cũng có thể định dạng biểu thức lọc của mình Any.
pholpar

1

Trong trường hợp ai đó cần xử lý một đối tượng động đến từ Json, tôi đã sửa đổi câu trả lời Seth Reno để xử lý đối tượng động được deserialized từ 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

Để mở rộng câu trả lời từ @Kuroro, nếu bạn cần kiểm tra xem thuộc tính trống hay không, bên dưới sẽ hoạt động.

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.