Kiểm tra xem thuộc tính có tồn tại trong một lớp không


82

Tôi cố gắng biết liệu một thuộc tính có tồn tại trong một lớp hay không, tôi đã thử điều này:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

Tôi không hiểu tại sao phương pháp kiểm tra đầu tiên không đậu?

[TestMethod]
public void Test_HasProperty_True()
{
    var res = typeof(MyClass).HasProperty("Label");
    Assert.IsTrue(res);
}

[TestMethod]
public void Test_HasProperty_False()
{
    var res = typeof(MyClass).HasProperty("Lab");
    Assert.IsFalse(res);
}

4
Bạn có phiền đăng mã liên quan từ MyClasskhông?
nattyddubbs

Câu trả lời:


126

Phương pháp của bạn trông giống như sau:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

Điều này thêm một phần mở rộng vào object- lớp cơ sở của mọi thứ . Khi bạn gọi phần mở rộng này, bạn đang chuyển nóType :

var res = typeof(MyClass).HasProperty("Label");

Phương thức của bạn mong đợi một phiên bản của một lớp, không phải mộtType . Nếu không, về cơ bản bạn đang làm

typeof(MyClass) - this gives an instanceof `System.Type`. 

Sau đó

type.GetType() - this gives `System.Type`
Getproperty('xxx') - whatever you provide as xxx is unlikely to be on `System.Type`

Như @PeterRitchie đã chỉ ra một cách chính xác, tại thời điểm này, mã của bạn đang tìm kiếm thuộc tính Label trên System.Type. Tài sản đó không tồn tại.

Giải pháp là

a) Cung cấp một phiên bản của MyClass cho tiện ích mở rộng:

var myInstance = new MyClass()
myInstance.HasProperty("Label")

b) Đặt phần mở rộng vào System.Type

public static bool HasProperty(this Type obj, string propertyName)
{
    return obj.GetProperty(propertyName) != null;
}

typeof(MyClass).HasProperty("Label");

2
tức là mã của bạn đang tìm kiếm `Type.Label , not MyClass.Label`.
Peter Ritchie

Làm thế nào người ta sẽ đưa nó vào System.Type của tiện ích mở rộng nơi mà sẽ được tìm thấy /. Điều này đi đâu trong mã để thực thi?
Demodave

1
@Demodave - các phương thức mở rộng chỉ nằm trong một lớp tĩnh công khai. Xem tại đây để biết thêm thông tin: msdn.microsoft.com/en-GB/library/bb383977.aspx
Jamiec

Nếu bạn gặp lỗi này: "Loại không chứa định nghĩa cho GetProperty" thì hãy đọc phần này: stackoverflow.com/questions/7858469/…
Tadej

26

Điều này trả lời một câu hỏi khác:

Nếu cố gắng tìm xem một OBJECT (không phải lớp) có thuộc tính hay không,

OBJECT.GetType().GetProperty("PROPERTY") != null

trả về true nếu (nhưng không chỉ nếu) thuộc tính tồn tại.

Trong trường hợp của tôi, tôi đang ở Chế độ xem một phần ASP.NET MVC và muốn hiển thị một cái gì đó nếu thuộc tính không tồn tại hoặc thuộc tính (boolean) là true.

@if ((Model.GetType().GetProperty("AddTimeoffBlackouts") == null) ||
        Model.AddTimeoffBlackouts)

đã giúp tôi ở đây.

Chỉnh sửa: Ngày nay, có lẽ sẽ thông minh khi sử dụng nameoftoán tử thay vì tên thuộc tính được xâu chuỗi.


Về việc sử dụng nameoftoán tử, nó sẽ hoạt động (không ném một ngoại lệ) để lấy tên của một thuộc tính có thể không tồn tại? Vì tiền đề của câu hỏi ban đầu là chúng ta không biết thuộc tính này có tồn tại hay không?
Zoe

Tại sao bạn không thử nó và sau đó chỉnh sửa câu trả lời của tôi để làm rõ?
Stachu

2

Có 2 khả năng.

Bạn thực sự không có Labeltài sản.

Bạn cần gọi quá tải GetProperty thích hợp và chuyển các cờ ràng buộc chính xác, ví dụ:BindingFlags.Public | BindingFlags.Instance

Nếu thuộc tính của bạn không được công khai, bạn sẽ cần sử dụng BindingFlags.NonPublichoặc một số kết hợp cờ khác phù hợp với trường hợp sử dụng của bạn. Đọc tài liệu API được tham chiếu để tìm chi tiết.

BIÊN TẬP:

Rất tiếc, chỉ nhận thấy bạn gọi GetPropertyvào typeof(MyClass). typeof(MyClass)Typecái chắc chắn không có Labeltài sản.


Các cờ ràng buộc mặc định được sử dụng là Instance|Public|Static, iirc.
LukeH

@LukeH, tôi không chắc, vì vậy tôi đã viết 'đúng' và thêm 'ví dụ' :) có thể Labellà tài sản riêng.
Zdeslav Vojkovic

1

Tôi gặp lỗi này: "Loại không chứa định nghĩa cho GetProperty" khi gắn câu trả lời được chấp nhận.

Đây là những gì tôi đã kết thúc với:

using System.Reflection;

if (productModel.GetType().GetTypeInfo().GetDeclaredProperty(propertyName) != null)
{

}

0

Nếu bạn đang ràng buộc như tôi:

<%# Container.DataItem.GetType().GetProperty("Property1") != null ? DataBinder.Eval(Container.DataItem, "Property1") : DataBinder.Eval(Container.DataItem, "Property2")  %>

0

Tôi không chắc về bối cảnh lý do tại sao điều này là cần thiết, vì vậy điều này có thể không trả lại đủ thông tin cho bạn nhưng đây là những gì tôi có thể làm:

if(typeof(ModelName).GetProperty("Name of Property") != null)
{
//whatevver you were wanting to do.
}

Trong trường hợp của tôi, tôi đang chạy qua các thuộc tính từ một lần gửi biểu mẫu và cũng có các giá trị mặc định để sử dụng nếu mục nhập bị để trống - vì vậy tôi cần biết liệu có giá trị để sử dụng hay không - tôi đã thêm tiền tố vào tất cả các giá trị mặc định của mình trong mô hình với Mặc định, vì vậy tất cả những gì tôi cần làm là kiểm tra xem có thuộc tính nào bắt đầu với điều đó không.

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.