2009-11-20 32 views
26

Tôi muốn tự động khám phá một số thông tin về một lớp được cung cấp để thực hiện điều gì đó giống như việc nhập biểu mẫu. Cụ thể là tôi đang sử dụng sự phản chiếu để trả về giá trị PropertyInfo cho mỗi thuộc tính. Tôi có thể đọc hoặc viết giá trị cho mỗi thuộc tính từ "biểu mẫu" của tôi, nhưng nếu thuộc tính được định nghĩa là "int", tôi sẽ không thể, và chương trình của tôi thậm chí không nên thử, để viết một giá trị null.Xác định xem thuộc tính phản ánh có thể được gán không

Làm cách nào tôi có thể sử dụng sự phản chiếu để xác định xem một thuộc tính nhất định có thể được gán giá trị rỗng không, không viết câu lệnh chuyển đổi để kiểm tra mọi loại có thể không? Đặc biệt, tôi muốn phát hiện sự khác biệt giữa các loại được đóng hộp như "int" so với "int?", Vì trong trường hợp thứ hai, tôi làm muốn có thể ghi giá trị null. IsValueType và IsByRef dường như không thấy sự khác biệt.

public class MyClass 
{ 
    // Should tell me I cannot assign a null 
    public int Age {get; set;} 
    public DateTime BirthDate {get; set;} 
    public MyStateEnum State {get; set;} 
    public MyCCStruct CreditCard {get; set;} 

    // Should tell me I can assign a null 
    public DateTime? DateOfDeath {get; set;} 
    public MyFamilyClass Famly {get; set;} 
} 

Lưu ý rằng tôi cần phải xác định thông tin này trước khi tôi thực sự cố gắng ghi giá trị, vì vậy sử dụng xử lý ngoại lệ được bao quanh SetValue không phải là một tùy chọn.

Trả lời

62

Bạn cần phải xử lý tài liệu tham khảo nullNullable<T>, vì vậy (lần lượt):

bool canBeNull = !type.IsValueType || (Nullable.GetUnderlyingType(type) != null); 

Lưu ý rằng IsByRef có gì đó khác biệt, cho phép bạn chọn giữa intref int/out int.

+1

Một cái gì đó tôi đã không nghĩ về nhưng tôi đã kiểm tra câu trả lời của bạn chống lại là mảng, chẳng hạn như int [] (có thể được gán null). Câu trả lời của bạn cũng đúng cho trường hợp này. – David

+2

Mảng là kiểu tham chiếu, vì vậy chúng hoạt động giống như các lớp. –

+0

Tôi nghĩ rằng cần lưu ý rằng trong OP, có những ví dụ sử dụng một int? và DateTime ?, do đó, kiểm tra đầu tiên sẽ trả về true (! type.IsValueType). Tôi làm như thế này tốt hơn so với một trong MSDN, nhưng tò mò tại sao bạn thêm vào những gì có vẻ là một kiểm tra dự phòng. Có lẽ, bởi vì bạn muốn đối phó với tất cả các trường hợp ngoài những gì được yêu cầu? – pqsk

9

Từ http://msdn.microsoft.com/en-us/library/ms366789.aspx

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 

Type sẽ là của bạn PropertyInfo.PropertyType

+1

Điều đó chỉ trả về giá trị mặc định. Làm việc cho DateTime ?, nhưng không phải cho MyFamilyClass, vì đó không phải là một chung chung, nhưng vẫn là một loại có thể được gán một giá trị null –

+0

Vâng, đúng vậy. –

+0

Điều này làm việc cho tôi, trong khi câu trả lời của Marc thì không. –

4
PropertyInfo propertyInfo = ... 
bool canAssignNull = 
    !propertyInfo.PropertyType.IsValueType || 
    propertyInfo.PropertyType.IsGenericType && 
     propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) 
+0

Sử dụng PropertyInfo có nhiều chi phí hơn sử dụng loại trực tiếp. Nhưng có thể hữu ích nếu bạn cần các tính năng bổ sung cho những thứ khác trên đường. – TamusJRoyce

0

Cả Marc và Jonas đều có các phần để xác định xem loại chung có thể được gán không.

// A silly example. default(T) will return null if it is nullable. So no reason to check here. Except for the sake of having an example. 
public U AssignValueOrDefault<U>(object item) 
{ 
    if (item == null) 
    { 
     Type type = typeof(U); // Type from Generic Parameter 

     // Basic Types like int, bool, struct, ... can't be null 
     // Except int?, bool?, Nullable<int>, ... 
     bool notNullable = type.IsValueType || 
          (type.IsGenericType && type.GetGenericTypeDefinition() != typeof(Nullable<>))); 

     if (notNullable) 
      return default(T); 
    } 

    return (U)item; 
} 

Lưu ý: Hầu hết thời gian bạn có thể kiểm tra xem biến có rỗng không. Sau đó, sử dụng mặc định (T). Nó sẽ trả về null theo mặc định của đối tượng là một lớp.

Các vấn đề liên quan