2011-07-10 17 views
7

मुझे सी # का उपयोग करके प्रतिबिंब के माध्यम से एक प्रकार पर विधियों को आमंत्रित करने की आवश्यकता है।सी # में प्रतिबिंब का उपयोग करते हुए विधि का आह्वान करते समय पैरामीटर के लिए स्वचालित प्रकार रूपांतरण कैसे करें?

रन-टाइम पर, मेरे डेटा में एक शब्दकोश होगा जिसमें नाम/मूल्य जोड़े होंगे। शब्दकोश में नाम मैं जिस विधि का आह्वान करूंगा उस पर पैरामीटर नामों के अनुरूप होगा। साथ ही, रन-टाइम पर, मेरे पास एक मनमाना असेंबली योग्य प्रकार का नाम और एक विधि नाम होगा। डिज़ाइन समय पर, मुझे प्रकार और विधि का कोई ज्ञान नहीं होगा, यह विधि टाइप int, स्ट्रिंग, डेटटाइम, बूल, int [], स्ट्रिंग [], डेटटाइम [] या बूल के पैरामीटर की एक चर संख्या को स्वीकार करेगी []।

मुझे उस बिंदु पर कोई समस्या नहीं है जहां मैं प्रतिबिंब का उपयोग करके प्रकार का उदाहरण बना सकता हूं और विधि का आह्वान कर सकता हूं। मैं बिंदु जहां मैं विधि जब मैं फोन द्वारा आवश्यक उचित प्रकार के लिए मेरे शब्दकोश में स्ट्रिंग मान परिवर्तित करने के लिए है पर अटक कर रहा हूँ:

someMethodInfo.Invoke(instance, new [] { ... }) 

मुझे पता है कि मैं शायद MethodInfo.GetParameters के माध्यम से गणना करने की जरूरत है() और प्रत्येक पैरामीटर के लिए प्रकार रूपांतरण प्रदर्शन करते हैं। मैं यह समझने की कोशिश कर रहा हूं कि यह कैसे करें, और आदर्श रूप से, इसे कुशलतापूर्वक कैसे करें।

मेरे शोध में अब तक एमवीसी स्रोत कोड में खुदाई शामिल है क्योंकि यह एक्शनमेड में फॉर्म वैल्यू पास करते समय कुछ समान होता है। मुझे ActionMethodDispatcher मिला लेकिन यह LINQ अभिव्यक्तियों का उपयोग करता है, जिसके साथ मैं अपरिचित हूं।

मैंने एसओ पर भी इसी तरह के प्रश्नों को देखा, लेकिन मेरे प्रश्न का उत्तर देने वाले कुछ भी नहीं मिला।

मैं किसी समाधान के लिए किसी भी पॉइंटर्स का स्वागत करता हूं।

+0

इसके बारे में जाने के लिए बेहतर तरीके हो सकते हैं, लेकिन मैं का उपयोग किया है [System.Convert] (http://msdn.microsoft.com/en-us/library/system। convert.aspx) समान आवश्यकताओं के लिए। नूलबे प्रकारों से निपटने से कुछ अतिरिक्त जटिलता भी मिलती है। – Clayton

+0

अधिक मनमानी रूपांतरण के लिए एक और विकल्प [TypeConverter] है (http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter (v = VS.100) .aspx), हालांकि मैं नहीं हूं सुनिश्चित करें कि यह सरणी के साथ कैसे काम करेगा। –

+0

@ क्लेटन हां, मुझे लगता है कि सिस्टम। अगर कुछ और सुरुचिपूर्ण नहीं है तो कनवर्ट मेरी फॉलबैक होगी।ऐसा लगता है कि प्रत्येक पैरामीटर प्रकार के माध्यम से लूपिंग और सिस्टम का उपयोग करने से अधिक कुशल तरीका हो सकता है। व्यक्तिगत प्रकार के रूपांतरण करने के लिए स्विच (...) में कनवर्ट करें। –

उत्तर

3

यहाँ कुछ कोड है जो मानकों के रूपांतरण के लिए इस्तेमाल किया जा सकता है। इस मामले में जब आप उन प्रकारों का उपयोग करने जा रहे हैं जो IConvertible इंटरफ़ेस का समर्थन नहीं करते हैं - तो प्रत्येक व्यक्तिगत प्रकार के लिए कस्टम कन्वर्टर्स को कार्यान्वित करना बेहतर होता है।

यह लिंक के साथ अधिक सुरुचिपूर्ण तरीके से लिखा जा सकता है।

विटालि

2

शायद "कन्वर्टर्स" का प्रबंधन करने का एक अच्छा तरीका Dictionary<Type, IMyTypeConverter> बनाए रखना है - जहां IMyTypeConverter में object Convert(string value) है।

public object ConvertSingleItem(string value, Type newType) 
{ 
    if (typeof(IConvertible).IsAssignableFrom(newType)) 
    { 
     return Convert.ChangeType(value, newType); 
    } 
    else 
    { 
     // TODO: Add custom conversion for non IConvertible types 
     var converter = CustomConvertersFactory.GetConverter(newType); 
     return converter.Convert(value); 
    } 
} 

public object ConvertStringToNewNonNullableType(string value, Type newType) 
{ 
    // Do conversion form string to array - not sure how array will be stored in string 
    if (newType.IsArray) 
    { 
     // For comma separated list 
     Type singleItemType = newType.GetElementType(); 

     var elements = new ArrayList(); 
     foreach (var element in value.Split(',')) 
     { 
      var convertedSingleItem = ConvertSingleItem(element, singleItemType); 
      elements.Add(convertedSingleItem); 
     } 
     return elements.ToArray(singleItemType); 
    } 
    return ConvertSingleItem(value, newType); 
} 

public object ConvertStringToNewType(string value, Type newType) 
{ 
    // If it's not a nullable type, just pass through the parameters to Convert.ChangeType 
    if (newType.IsGenericType && newType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 
    { 
     if (value == null) 
     { 
      return null; 
     } 
     return ConvertStringToNewNonNullableType(value, new NullableConverter(newType).UnderlyingType); 
    } 
    return ConvertStringToNewNonNullableType(value, newType); 
} 

public object CallMethod(object instance, MethodInfo methodInfo, Dictionary<string, string> parameters) 
{ 
    var methodParameters = methodInfo.GetParameters(); 

    var parametersForInvocation = new List<object>(); 
    foreach (var methodParameter in methodParameters) 
    { 
     string value; 
     if (parameters.TryGetValue(methodParameter.Name, out value)) 
     { 
      var convertedValue = ConvertStringToNewType(value, methodParameter.ParameterType); 
      parametersForInvocation.Add(convertedValue); 
     } 
     else 
     { 
      // Get default value of the appropriate type or throw an exception 
      var defaultValue = Activator.CreateInstance(methodParameter.ParameterType); 
      parametersForInvocation.Add(defaultValue); 
     } 
    } 
    return methodInfo.Invoke(instance, parametersForInvocation.ToArray()); 
} 

यह आदिम प्रकार, Nullables और आदिम प्रकार के एरे का समर्थन करता है:

4

मूल्य आप कन्वर्ट करने के लिए एक ऑब्जेक्ट होना चाहिए चाहते हैं, अन्यथा मानक प्रकार के बाहर रूपांतरण काम नहीं करेगा। आप आसानी से इस तरह के प्रकारों के बीच रूपांतरित कर सकते हैं:

object value = false; // false 
Type chType = typeof(String); // System.String 
object newValue = Convert.ChangeType(value, chType); // "false" 

यह उतना आसान है जितना आसान है। यदि आप एक विधि चाहते हैं:

public object ConvertType(object value, Type conversionType) 
{ 
    //Check if type is Nullable 
    if (conversionType.IsGenericType && 
     conversionType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
    { 
     //If the type is Nullable and the value is null 
     //Just return null 
     if (value == null) 
     { 
      return null; 
     } 

     //Type is Nullable and we have a value, override conversion type to underlying 
     //type for the Nullable to avoid exception in Convert.ChangeType 
     var nullableConverter = new NullableConverter(conversionType); 
     conversionType = nullableConverter.UnderlyingType; 
    } 

    return Convert.ChangeType(value, conversionType); 
} 
+0

जैसा कि मैंने अपनी टिप्पणियों में उल्लिखित प्रकारों में उल्लेख किया है, कुछ विशेष केस हैंडलिंग की आवश्यकता है। मैंने आपकी विधि को संशोधित करने के लिए संशोधित किया है कि आप – Clayton

+0

@ क्लेटन, धन्यवाद के बारे में कैसे जा सकते हैं। –

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