2011-03-23 75 views
5

我嘗試一般轉換用戶輸入簡單或複雜的類型一般System.String要任何複雜類型:轉換使用「Convert.ChangeType()」

class Program 
{ 
    static void Main(string[] args) 
    { 
    Console.WriteLine("Welcome, please provide the following info... Confirm with <RETURN>!"); 
    Console.WriteLine();  

    Console.Write("Name (e.g. 'Peggy Sue'): "); 
    var user = GetUserInput<User>(Console.ReadLine()); 

    Console.WriteLine(); 
    Console.WriteLine(); 
    Console.WriteLine("Hi {0}, nice to meet you!", user.Forename); 
    Console.WriteLine(); 

    Console.Write("Age: "); 
    user.Age = GetUserInput<ushort>(Console.ReadLine()); 

    Console.WriteLine(); 
    Console.WriteLine("Thanks and goodbye!"); 
    Console.WriteLine("Press <RETURN> to quit..."); 
    Console.ReadLine(); 
    } 

    static T GetUserInput<T>(string data) 
    { 
    return (T) Convert.ChangeType(data, typeof (T)); 
    } 
} 

class User 
{ 
    public User(string name) 
    { 
    var splitted = name.Split(' '); 
    Forename = splitted[0]; 
    Lastname = splitted[1]; 
    } 

    public static implicit operator User (string value) 
    { 
    return new User(value); 
    } 

    public static explicit operator string (User value) 
    { 
    return string.Concat(value.Forename, " ", value.Lastname); 
    } 

    public string Forename { get; private set; } 
    public string Lastname { get; private set; } 

    public ushort Age { get; set; } 
} 

有關轉換到我的「用戶」類,我總是得到異常「從'System.String'轉換爲'ConsoleApplication1.User'。」。有誰知道如何解決這一問題?

如果我嘗試這樣的事情(不一般),它只是完美:

Console.WriteLine((string) ((User) "Peggy Sue")); 
+0

User對象是否提供默認構造函數? – 2011-03-23 07:03:13

回答

5

這裏的一個選擇可能是將TypeConverter與您關心的類型相關聯(您可以在編譯時通過[TypeConverter(...)]執行此操作,或者如果您不控制類型,則可以在運行時執行此操作) 。

然後,它是:

TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); 
T obj = (T)conv.ConvertFromString(text); // or ConvertFromInvariantString 
+0

聽起來不錯!如何將我的類「用戶」作爲「TypeConverter」對象引入?我得到一個「NotSupportedException」,說「TypeConverter無法從System.String轉換。」! – Maik 2011-03-23 07:51:40

+0

太棒了,找到了! :) – Maik 2011-03-23 07:54:58

6

沒有,Convert.ChangeType只適用於一組固定的類型,我相信......或者,如果原來的對象實現IConvertible,它可以調用IConvertible.ToType。這意味着你可以User類實現IConvertible並有

Convert.ChangeType(user, typeof(string)) 

工作,但不會工作倒過來。

你有固定的一組類型需要轉換嗎?如果是這樣,你可以有一個Dictionary<Type, Func<string, object>>,你將填入轉換代表。然後您只需調用適當的轉換並轉換返回值即可。這很醜陋,但可能是你最好的選擇。

0

如果你正在尋找轉換爲數值類型,我更喜歡更簡潔和意圖曝光:

decimal.Parse(someString) 

或者,在你的榜樣:

new User(userName) 

沒有理由創建整個方法(或類,如果你決定在將來「使這個可重用」)只是包裝演員。當語言已經具有較不透明的方式來表達代碼的意圖時,情況尤其如此。

+0

是的你是對的,但我發佈的示例只是實際GetUserInput方法的一個簡單示例。例如: static T GetUserInput () var input = Console.ReadLine();如果(string.IsNullOrEmpty(輸入)|| input.Trim()== string.Empty) return GetUserInput (); return(T)Convert.ChangeType(input,typeof(T)); } – Maik 2011-03-23 07:44:26

+0

@Maik:你應該分解這段代碼,因爲它做了兩件事(接受用戶輸入和解析用戶輸入)。儘管代碼很短,並且。Net似乎支持這種情況,將這種類型的東西結合在你的設計中通常會讓你對更大的項目感興趣。見http://en.wikipedia.org/wiki/Single_responsibility_principle – 2011-03-23 08:01:31

2

我固定它。選中此項:

class Program 
{ 
    static void Main(string[] args) 
    { 
    Console.WriteLine("Welcome, please provide the following info... Confirm with <RETURN>!"); 
    Console.WriteLine(); 

    Console.Write("Name (e.g. 'Peggy Sue'): "); 
    var user = GetUserInput<User>(Console.ReadLine()); 

    Console.WriteLine(); 
    Console.WriteLine(); 
    Console.WriteLine("Hi {0}, nice to meet you!", user.Forename); 
    Console.WriteLine(); 

    Console.Write("Age: "); 
    user.Age = GetUserInput<ushort>(Console.ReadLine()); 

    Console.WriteLine(); 
    Console.WriteLine("Thanks and goodbye!"); 
    Console.WriteLine("Press <RETURN> to quit..."); 
    Console.ReadLine(); 
    } 

    static T GetUserInput<T>(string data) 
    { 
    TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); 
    return (T) conv.ConvertFromInvariantString(data); 
    } 
} 

[TypeConverter(typeof(UserConverter))] 
class User 
{ 
    public User(string name) 
    { 
    var splitted = name.Split(' '); 
    Forename = splitted[0]; 
    Lastname = splitted[1]; 
    } 

    public static explicit operator User (string value) 
    { 
    return new User(value); 
    } 

    public static explicit operator string (User value) 
    { 
    return string.Concat(value.Forename, " ", value.Lastname); 
    } 

    public string Forename { get; private set; } 
    public string Lastname { get; private set; } 

    public ushort Age { get; set; } 
} 

class UserConverter : TypeConverter 
{ 
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
    return (typeof(string) == sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
    { 
    if (value is string) 
    { 
     return (User)(value as string); 
    } 

    return null; 
    } 
} 
+0

感謝分享!這是一個很好的解決方案。我已經在使用反射來尋找與目標類型匹配的隱式運算符,但這更優雅! – 2017-06-25 19:21:48