2010-01-22 34 views
6

Tôi có một lớp phân tích dữ liệu từ tệp văn bản được phân tách bằng dấu phẩy. Tôi có một enum cho các lĩnh vực để giúp tôi phân tích dữ liệu trong dễ dàng hơn. Lớp phân tích tất cả các bản ghi trong giữ các biến công khai cho từng trường, và tất nhiên là các kiểu biến của chúng. Tôi cần lấy loại biến này dựa trên enum đã cho.C# Nhận loại biến công khai dựa trên giá trị Enum

public enum DatabaseField : int 
    { 
     NumID1 = 1, 
     NumID2 = 2, 
     NumID3 = 3, 
    }; 

public class DataBaseRecordInfo 
    { 
     public long NumID1 { get; set; } 
     public int NumID2 { get; set; } 
     public short NumID3 { get; set; } 

     public static Type GetType(DatabaseField field) 
     { 
      Type type; 

      switch (field) 
      { 
       case DatabaseField.NumID1: 
        type = typeof(long); 
        break; 
       case DatabaseField.NumID2: 
        type = typeof(int); 
        break; 
       case DatabaseField.NumID3: 
        type = typeof(short); 
        break; 
       default: 
        type = typeof(int); 
        break; 
      } 

      return type; 
     } 
    }; 

NumID1, NumID2, NumID3 tất cả được chỉ định trong hàm tạo của tôi. Tuy nhiên, tôi muốn nhận các loại này mà không bao giờ tạo ra một thể hiện của DataBaseRecordInfo. Ngay bây giờ phương pháp tĩnh của tôi ở trên sẽ làm việc, tuy nhiên, nếu tôi muốn thay đổi loại biến, tôi sẽ phải thay đổi nó ở 2 nơi. Có cách nào để tránh phải thay đổi điều này ở cả hai nơi và giữ nó như một phương pháp tĩnh?

+0

Tôi không hiểu câu hỏi. Bạn có thể rõ ràng hơn không? "Tuy nhiên, tôi muốn có được những kiểu này mà không bao giờ tạo ra một thể hiện của DataBaseRecordInfo" - điều đó có nghĩa là gì? – hackerhasid

+0

Nó có nghĩa là tôi có scenerios mà tôi muốn các loại biến đó, nhưng không muốn khởi tạo lớp này để lấy các loại. – jsmith

Trả lời

4

Nếu tên luôn khớp chính xác, bạn có thể thực hiện việc này bằng cách sử dụng sự phản chiếu.

return typeof(DataBaseRecordInfo) 
    .GetProperty(field.ToString(), BindingFlags.Public | BindingFlags.Instance) 
    .PropertyType; 

Bạn thậm chí có thể lưu các giá trị này trong từ điển, vì vậy nếu tìm thấy, chỉ cần trả lại mục nhập từ điển, nếu không xác định bằng cách sử dụng phản chiếu và lưu kết quả.

+0

+1 Tôi cũng nghĩ về câu trả lời từ điển, nhưng tôi thích cách phản chiếu tốt hơn – SwDevMan81

+0

Cách tiếp cận lai này đánh dấu tất cả các hộp IMHO –

+0

Haha, cái gì? Ticks tất cả các hộp, tôi phải đã bỏ lỡ một cái gì đó ... thậm chí không thể tìm thấy một trong từ điển của hacker mới, có thể là một thời gian cho một phiên bản? – SwDevMan81

0

Có, bạn có thể sử dụng tên trong enum cùng với sự phản ánh trên loại DatabaseRecordInfo để có được các loại bạn cần.

Điều này có thể được thực hiện như thế này:

public class DataBaseRecordInfo 
{ 
    public long NumID1 { get; set; } 
    public int NumID2 { get; set; } 
    public short NumID3 { get; set; } 

    public static Type GetType(DatabaseField field) 
    { 
     string name = field.ToString(); 
     Type recordType = typeof (DataBaseRecordInfo); 
     var props = recordType.GetProperties(); 
     var matchedProperty = props.Where(p => name == p.Name).FirstOrDefault(); 
     if (matchedProperty == null) 
      return null; // We do not have a matching property. 
     return matchedProperty.PropertyType; 
    } 
}; 

Bạn có thể sẽ muốn để cache kết quả trong một cuốn từ điển, vì sự phản chiếu có thể tốn kém hiệu suất-khôn ngoan.

0

Làm thế nào về một cái gì đó như thế này:

public static Type GetType(DatabaseField field) 
{ 
    DataBaseRecordInfo dbri = new DataBaseRecordInfo(); 

    switch (field) 
    { 
    case DatabaseField.NumID1: 
     return dbri.NumID1.GetType(); 
    case DatabaseField.NumID2: 
     return dbri.NumID2.GetType(); 
    case DatabaseField.NumID3: 
    return dbri.NumID3.GetType(); 
    default: 
     return typeof(int); 
    } 
} 

Tôi biết bạn nói mà không bao giờ cần phải tạo một thể hiện của DataBaseRecordInfo nhưng tôi giả sử bạn có nghĩa là một thể hiện bên ngoài của phương pháp tĩnh. Không ai nhìn thấy trường hợp này.

+0

Điều này tạo ra một cá thể mỗi khi phương thức được gọi. Nó cũng không giải quyết vấn đề duy trì ở hai nơi. –

+0

Điều này sẽ không hoạt động vì một số lý do .. – jsmith

+0

Tôi có ấn tượng rằng vấn đề "duy trì ở hai nơi" bị hạn chế đối với các loại, điều này giải quyết khá tốt. Nó thậm chí còn mang lại cho bạn sự linh hoạt khi sử dụng các tên không khớp. – Sapph

0

Nếu bạn muốn ràng buộc giá trị enum với một số thông tin bổ sung, bạn có thể sử dụng CustomAttribute của riêng mình.

Có lẽ bạn cần một cái gì đó như thế này:

public class DatabaseTypeAttribute : Attribute 
{ 
    public DatabaseTypeAttribute(Type type) 
    { 
     Type = type; 
    } 
    public Type Type { get; private set; } 
} 

public enum DatabaseField : int 
{ 
    [DatabaseType(typeof(long))] 
    NumID1 = 1, 
    [DatabaseType(typeof(int))] 
    NumID2 = 2, 
    [DatabaseType(typeof(short))] 
    NumID3 = 3, 
    NumID4 = 4, 
}; 

public static class DatabaseFieldHelper 
{ 
    public static Type GetDatabaseType(this DatabaseField field) 
    { 
     var attributes = (DatabaseTypeAttribute[])typeof(DatabaseField).GetField(Enum.GetName(typeof(DatabaseField), field)) 
      .GetCustomAttributes(typeof(DatabaseTypeAttribute), false); 
     if (attributes.Length == 0) 
      return typeof(int); //returns default type 
     return attributes[0].Type; 

    } 
} 

//prints: NumID1 database type: System.Int64 
Console.WriteLine("NumID1 database type: {0}", DatabaseField.NumID1.GetDatabaseType()); 

//prints: NumID2 database type: System.Int32 
Console.WriteLine("NumID2 database type: {0}", DatabaseField.NumID2.GetDatabaseType()); 

//prints: NumID3 database type: System.Int16 
Console.WriteLine("NumID3 database type: {0}", DatabaseField.NumID3.GetDatabaseType()); 

//prints: NumID4 database type: System.Int32 
Console.WriteLine("NumID4 database type: {0}", DatabaseField.NumID4.GetDatabaseType()); 
Các vấn đề liên quan