2011-03-23 8 views
5

मैं सामान्य रूप से करने की कोशिश या तो सरल या जटिल प्रकार में उपयोगकर्ता इनपुट कन्वर्ट का उपयोग कर:Convert किसी भी जटिल प्रकार के सामान्य रूप से 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

उपयोगकर्ता ऑब्जेक्ट एक डिफ़ॉल्ट कन्स्ट्रक्टर प्रदान करता है ?? –

उत्तर

5

यहां एक विकल्प टाइप प्रकार कनवर्टर को उन प्रकारों से जोड़ना हो सकता है जिनकी आप परवाह करते हैं (आप इसे [TypeConverter(...)] के माध्यम से संकलित समय पर कर सकते हैं, या यदि आप प्रकारों को नियंत्रित नहीं करते हैं तो रनटाइम पर ऐसा करने के लिए एक चाल है) ।

तो यह है:

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

अच्छा लगता है! मैं अपनी कक्षा "उपयोगकर्ता" को "टाइप कनवर्टर" ऑब्जेक्ट के रूप में कैसे पेश कर सकता हूं? मुझे "NotSupportedException" कह रहा है, "TypeConverter System.String से कनवर्ट नहीं कर सकता।"! – Maik

+0

बहुत बढ़िया, यह पाया !!! :) – Maik

6

नहीं है, Convert.ChangeType केवल प्रकार की एक निश्चित सेट के साथ काम करता है, मेरा मानना ​​है कि ... या अगर मूल वस्तु औजार IConvertible, यह IConvertible.ToType पर कॉल कर सकता है। इसका मतलब है कि आप अपने User कक्षा में IConvertible को लागू कर सकते हैं और काम कर

Convert.ChangeType(user, typeof(string)) 

है, लेकिन है कि होगा दौर दूसरा रास्ता नहीं काम करते हैं।

क्या आपके पास परिवर्तित करने के लिए आवश्यक प्रकारों का एक निश्चित सेट है? यदि ऐसा है, तो आपके पास Dictionary<Type, Func<string, object>> हो सकता है जिसे आप रूपांतरण प्रतिनिधियों के साथ पॉप्युलेट करेंगे। फिर आपको उचित रूपांतरण को कॉल करने और वापसी मूल्य डालने की आवश्यकता है। यह बदसूरत है, लेकिन शायद आपकी सबसे अच्छी शर्त है।

decimal.Parse(someString) 

या, अपने उदाहरण में:

new User(userName) 

कोई कारण नहीं एक बनाने के लिए

0

आप सांख्यिक प्रकार कन्वर्ट करने के लिए देख रहे हैं, मैं बहुत खनन और इरादे-उजागर पसंद करते हैं पूरी विधि (या कक्षा, यदि आप भविष्य में "इसे पुन: प्रयोज्य बनाने" के लिए निर्णय लेते हैं) बस एक कास्ट लपेटने के लिए। यह विशेष रूप से सच है जब भाषा में आपके कोड के इरादे को व्यक्त करने के लिए पहले से ही कम अपारदर्शी तरीका है।

+0

हाँ आप सही हैं, लेकिन मैंने जो नमूना पोस्ट किया है वह वास्तविक GetUserInput विधि के लिए एक साधारण नमूना है। उदाहरण के लिए: स्थिर टी GetUserInput () { var input = Console.ReadLine(); यदि (string.IsNullOrEmpty (इनपुट) || input.Trim() == string.Empty) वापसी GetUserInput (); वापसी (टी) कनवर्ट करें। चेंजटाइप (इनपुट, टाइपोफ (टी)); } – Maik

+0

@ मिक: आपको शायद इस कोड को विभाजित करना चाहिए, क्योंकि यह दो अलग-अलग चीजें करता है (उपयोगकर्ता इनपुट स्वीकार कर रहा है, और उपयोगकर्ता इनपुट को पार्स कर रहा है)। हालांकि कोड छोटा है, और।नेट इस परिदृश्य का समर्थन करता प्रतीत होता है, इस प्रकार के सामान को आपके डिजाइन में संयोजित करने से आम तौर पर आपको बड़ी परियोजनाओं पर काट दिया जाएगा। देखें http://en.wikipedia.org/wiki/Single_responsibility_principle –

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

साझा करने के लिए धन्यवाद! यह इस के लिए एक अच्छा समाधान है। मैं पहले से ही लक्ष्य प्रकार से मेल खाने वाले निहित ऑपरेटरों को खोजने के लिए प्रतिबिंब का उपयोग करने पर काम कर रहा था, लेकिन यह बहुत अधिक सुरुचिपूर्ण है! –

संबंधित मुद्दे