2011-12-24 51 views
10

Tôi có tệp chứa một số biến của một lớp và mỗi dòng là một cặp: biến, giá trị. Tôi đang tìm một cách để tải những lúc chạy (a-la XmlSerializer), bằng cách sử dụng sự phản ánh.C# Chuỗi phân tích cú pháp để nhập được biết tại thời gian chạy

Có cách nào để phân tích cú pháp string thành một Type chỉ được biết khi chạy không?

Sau đây là một mẫu mã mơ tưởng nơi dòng cuối cùng (với pi.SetValue() là không đúng, bởi vì PropertyType là của lớp Type mà không có một Parse() generic method.

using (var sr = new StreamReader(settingsFileName)) 
{ 
    String line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     String[] configValueStrs = line.Trim().Split(seps); 

     PropertyInfo pi = configurableProperties 
       .Single(p => p.Name == configValueStrs[0].Trim()); 

     //How do I manage this? 
     pi.SetValue(this, pi.PropertyType.Parse(configValueStrs[1].Trim()), null); 
    } 
} 

Kể từ khi tất cả các liên quan biến là Ints, Doubles, Strings hoặc Booleans, như là phương sách cuối cùng, tôi có thể bật kiểu và sử dụng phương thức ToType() tương ứng, nhưng tôi đặt cược là một giải pháp thanh lịch hơn.

Trả lời

7

Bạn có thể sử dụng phương pháp Convert.ChangeType tĩnh cho điều đó. Nó lấy một đối tượng làm tham số đầu tiên của nó và một cá thể Type mà bạn muốn chuyển đổi đối tượng thành. Giá trị trả về là loại bạn yêu cầu hoặc null nếu không tìm thấy chuyển đổi phù hợp. Phương thức này ném 4 ngoại lệ khác nhau, trong đó ba trường hợp được gây ra bởi giá trị mà nó cố gắng chuyển đổi. Bạn có thể muốn nắm bắt và xử lý chúng.

Sử dụng các chức năng như sau trong ví dụ của bạn:

// Convert.ChangeType can throw if the string doesn't convert to any known type 
    pi.SetValue(this 
     , Convert.ChangeType(configValueStrs[1], pi.PropertyType) 
     , null); 
17

TypeConverters là con đường để đi. Hãy xem here để có ví dụ điển hình về những việc cần làm.

nicked thẳng từ hanselmans blog:

public static T GetTfromString<T>(string mystring) 
{ 
    var foo = TypeDescriptor.GetConverter(typeof(T)); 
    return (T)(foo.ConvertFromInvariantString(mystring)); 
} 
+0

+1 với điều này vì nó sẽ xử lý GUIDS, Convert.ChangeType sẽ không – Arical

+0

Cảm ơn, đã giúp tôi thoát khỏi tình huống dính! – Peter

-2

tôi có nhiệm vụ tương tự để nạp biến của một lớp, sử dụng phản ánh. Tôi tải các chuỗi cặp khóa/giá trị từ một tệp, sau đó tôi phân tích các giá trị dựa trên các định nghĩa của các biến tương ứng từ lớp cài đặt của tôi.

Tóm lại, tôi sử dụng đoạn mã sau (phương pháp FieldInfo.SetValue (Object, Object) là chìa khóa ở đây, bởi vì nó không đòi hỏi bất kỳ loại chuyển đổi giá trị Object, trả về bởi TypeConverter.ConvertFromString phương pháp):

using System.Reflection; 
using System.ComponentModel; 
using System.Globalization; 

.... 

Settings settings = new Settings(); // my Settings class with variables to load 
FieldInfo[] fields = settings.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static); 
.... 

foreach (var field in fields) 
{ 
    if (key.KeyName == field.Name) 
    { 
     try 
     { 
      field.SetValue(settings, TypeDescriptor.GetConverter(field.FieldType).ConvertFromString(null, CultureInfo.InvariantCulture, key.Value)); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Error: The value string \"{0}\" isn't parsed!", key.Value); 
      //Console.WriteLine(ex.ToString()); 
     } 
     break; 
    } 
} 
Các vấn đề liên quan