2011-12-19 22 views
6

Tôi có đoạn mã sau đó tạo ra một DLL (mẫu dụ):Biết nếu Trường/Thuộc tính của một đối tượng là các loại "đơn giản/nguyên thủy" hoặc các đối tượng khác?

public class PluginClass 
{ 
    private string _MyString; 
    public string MyString 
    { 
     get { return _MyString; } 
     set 
     { 
      _MyString = value; 
      RaisePropertyChanged("MyString"); 
     } 
    } 

    public int MyInt; 

    public SpeedGenerator SpeedGenerator1 = new SpeedGenerator(); 

    public GaugeValueGenerator GaugeValueGenerator1 
    { 
     get; 
     set; 
    } 

    public PluginClass() 
    { 
     GaugeValueGenerator1 = new GaugeValueGenerator(); 
    } 
} 

Như bạn có thể thấy tôi có 4 lĩnh vực/tài sản.

1 lĩnh vực nguyên thủy (nguyên thủy là int/chuỗi/bool/etcetc ...): Myint 1 nguyên thủy bất động sản: mystring lĩnh vực 1 đối tượng: SpeedGenerator1 sở hữu 1 đối tượng: GaugeValueGenerator1

Khi Im phân tích DLL của tôi tôi đã làm một số mã đó là trong hàm: WriteProperty

var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); 
var props = type.GetProperties(); 

foreach (FieldInfo field in fields) 
{ 
    WriteProperty(field.FieldType, field.Name, XXX); 
} 

foreach (PropertyInfo prop in props) 
{ 
    WriteProperty(prop.PropertyType, prop.Name, XXX); 
} 

câu hỏi của tôi là trên XXX đó là một boolean cho biết nếu lĩnh vực của tôi/tài sản là "nguyên thủy". Vì vậy, nó phải được đặt thành false nếu nó là một đối tượng. Tôi rơi như tôi đã thử tất cả mọi thứ nhưng tôi không thể giải quyết nó ... Bất kỳ trợ giúp nào cũng sẽ rất được đánh giá cao!

(Ý tưởng của tôi là để gọi

var props = propertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); 

và xem xét rằng nó nên được bỏ trống với nhiều loại đơn giản/nguyên thủy! Nhưng không ... ví dụ trên String, này trả lại thuộc tính Chars (char []) và Chiều dài (int) ...)

(nb: Tất nhiên tôi không muốn làm một thao tác chuỗi trên sân/property.Name/FullName ... cái gì đó như

if ((propertyType.FullName).Contains("System.")) 

sẽ rất rất sucky ... và không chính xác)

+0

Bạn sẽ phải xác định ý nghĩa của từ "nguyên thủy". Bạn có muốn xử lý 'chuỗi' như một nguyên thủy, mặc dù nó là một kiểu tham chiếu? Bạn có xem 'DateTime' là nguyên thủy không? Điều gì về 'Guid', hoặc' enum's, hoặc 'System.Object'? –

+0

Đã trả lời trong phần bình luận của câu trả lời được đánh giá cao nhất (tại thời điểm này) –

+0

Kiểm tra "Hệ thống" trong tên đầy đủ cũng không thực sự không an toàn. Không có gì ngăn ai đó tạo một lớp với tên đầy đủ chứa "Hệ thống". ngay cả khi nó không được khuyến khích. – InBetween

Trả lời

5

Tại sao không sử dụng IsPrimitive của lớp học Type?

XXX = field.FiledType.IsPrimitive 

EDIT: Bạn sẽ phải điều trị string như một trường hợp đặc biệt như IsPrimitive sẽ không trở lại true.

CHỈNH SỬA 2: Sự cố bạn đang gặp phải là bạn đang cố gắng kết hôn với hai định nghĩa primitve không phù hợp. Là rằng trường hợp tôi chỉ có thể nhìn thấy hai lựa chọn:

  1. Make cả định nghĩa trận đấu mà rõ ràng là bạn không thể làm thay đổi hệ thống kiểu CLR và có lẽ không thể làm một trong hai thay đổi khuôn khổ bạn đang sử dụng.

  2. Làm cho một số hack rằng "kết hôn" cả hai định nghĩa. Tôi không thấy cách nào khác xung quanh mã hóa cứng các trường hợp ngoại lệ cụ thể không khớp với một trong hai định nghĩa của các loại primitve.

+0

trả về false trên MyString trong ví dụ của tôi:/doesnt work –

+0

Vâng, chỉnh sửa câu trả lời của tôi. Chỉ cần đưa ra một phương thức trợ giúp làPrimitve (Type t) để kiểm tra xem nó có phải là nguyên thủy hay 'chuỗi'. Bạn haveto mã cứng vài ngoại lệ bạn biết bạn có thể chạy vào (thập phân, DateTime, vv) vì chúng không thực sự là mồi. – InBetween

+0

Ok với chỉnh sửa nhưng câu trả lời của LukeH dường như chỉ ra rằng chuỗi không phải là ngoại lệ duy nhất ... :(Nếu có rất nhiều ngoại lệ, điều này không tốt để đối xử với tất cả chúng một cách riêng biệt: ( –

2

Bạn có thể sử dụng field.FieldType.IsPrimitiveprop.PropertyType.IsPrimitive, nhưng bạn sẽ phải thất vọng nếu bạn đang mong string, decimal vv để được coi là nguyên thủy.

Tại sao không tạo tập hợp các loại riêng của bạn mà bạn coi là nguyên thủy và kiểm tra điều đó?

WriteProperty(f.FieldType, f.Name, yourPrimitives.Contains(f.FieldType)); 

// ... 

WriteProperty(p.PropertyType, p.Name, yourPrimitives.Contains(p.PropertyType)); 

// ... 

private static readonly HashSet<Type> yourPrimitives = new HashSet<Type> 
    { 
     typeof(int), typeof(string), typeof(decimal) // etc 
    }; 

Một lựa chọn khác là sử dụng GetTypeCode và sau đó kiểm tra xem kết quả không phải là TypeCode.Object, TypeCode.DBNull vv Nó thực sự phụ thuộc vào chính xác những gì yêu cầu của bạn, và chính xácbạn xem xét để là một kiểu nguyên thủy.

+0

Vâng, và tôi đã xử lý Strings: ( –

4

Điều này sẽ thực hiện.

public static bool IsPrimate(this object obj) 
    { 
     return new[] 
     { 
      typeof (Enum), 
      typeof (String), 
      typeof (Char), 
      typeof (Guid), 
      typeof (Boolean), 
      typeof (Byte), 
      typeof (Int16), 
      typeof (Int32), 
      typeof (Int64), 
      typeof (Single), 
      typeof (Double), 
      typeof (Decimal), 
      typeof (SByte), 
      typeof (UInt16), 
      typeof (UInt32), 
      typeof (UInt64), 
      typeof (DateTime), 
      typeof (DateTimeOffset), 
      typeof (TimeSpan), 
     }.Any(oo => oo.IsInstanceOfType(obj)); 
    } 
+0

Tôi chỉ nhận thấy điều này nói, 'IsPrimate', không phải 'IsPrimitive '. – Ermish

+1

@ Tôi biết - đó là một trò đùa. –

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