2010-12-31 8 views
5

मैं प्रतिबिंब का उपयोग करके एक सरणी बनाने की कोशिश कर रहा हूं, और इसमें मान डाल सकता हूं। ,सी # ऐरे के लिए रनटाइम पर कास्टिंग टाइप करें। SetValue

public class A{ 
    public A(){} 

    private double val; 
    public double Value{ 
     get{ return val; } 
     set{ this.val = value; } 
    } 

    public static implicit operator A(double d){ 
     A a = new A(); 
     a.Value = d; 
     return a; 
    } 
} 

और वर्ग बी बहुत समान होने: वर्ग के साथ एक से किया जा रहा

String propertyName1 = "prop1"; 
String propertyName2 = "prop2"; 

Type t1 = typeof(myType).getProperty(propertyName1).PropertyType.getElementType(); 
Type t2 = typeof(myType).getProperty(propertyName2).PropertyType.getElementType(); 

double exampleA = 22.5; 
int exampleB = 43; 

Array arrA = createAndFillArray(t1, exampleA); 
Array arrB = createAndFillArray(t2, exampleB); 

private Array createAndFillArray(Type t, object val){ 
    Array arr = Array.CreateInstance(t, 1); //length 1 in this example only, real-world is of variable length. 
    arr.SetValue(val, 0); //this causes the following error: "System.InvalidCastException : Object cannot be stored in an array of this type." 
    return arr; 
} 

इस प्रकार है: मैं तो एक createAndFillArray समारोह इस में सक्षम चाहते हैं कई अलग अलग प्रकार के लिए यह करने के लिए कोशिश कर रहा हूँ लेकिन int साथ:

:

public class B{ 
    public B(){} 

    private double val; 
    public double Value{ 
     get{ return val; } 
     set{ this.val = value; } 
    } 

    public static implicit operator B(double d){ 
     B b = new B(); 
     b.Value = d; 
     return b; 
    } 
} 

और MyType निम्नलिखित की तरह कुछ है

public class myType{ 
    public A prop1{ get; set; } 
    public B prop2{ get; set; } 
} 

मुझे उम्मीद थी कि निहित ऑपरेटर यह सुनिश्चित करेगा कि डबल को कक्षा ए में परिवर्तित किया जाए, या कक्षा बी से int, और त्रुटि से बचा जाए; लेकिन यह स्पष्ट रूप से ऐसा नहीं है।

उपर्युक्त कस्टम deserialization वर्ग में उपयोग किया जाता है, जो एक कस्टम डेटा प्रारूप से डेटा लेता है और संबंधित .Net ऑब्जेक्ट गुणों में भरता है। मैं प्रतिबिंब और रनटाइम के माध्यम से ऐसा कर रहा हूं, इसलिए मुझे लगता है कि दोनों अपरिहार्य हैं। मैं सी # 2.0 ढांचे को लक्षित कर रहा हूं।

मैं दर्जनों, नहीं तो सैकड़ों, A और B के समान वर्गों की है, तो एक समाधान है जो एक समाधान है जो इन कक्षाओं में बदल बजाय createAndFillArray विधि में सुधार को खोजने के लिए पसंद करेंगे।

+0

क्यों का उपयोग कर नहीं है 'सार्वजनिक दसवीं कक्षा ' एक ही कक्षा के बजाय सिर्फ विभिन्न सदस्य प्रकार:

से कॉपी किया गया? –

+1

[लागू रूपांतरणों को संकलन समय पर हल किया जाना चाहिए।] (Http://philosopherdeveloper.wordpress.com/2010/05/05/the-difference-between-converting-and-unboxing-read-my-mind-compiler /) एक अनबॉक्सिंग ऑपरेशन जादुई रूप से एक निहित रूपांतरण नहीं करेगा जब संकलक समय से पहले के प्रकारों को नहीं जानता था। एक ही नियम सभी विधि अधिभार संकल्प मामलों पर लागू होता है। –

+0

@ सईद यह सबसे अच्छा होगा, लेकिन दुर्भाग्य से कक्षाएं ए, बी, सी आदि .. विरासत हैं और मैं उन्हें बदलने के बारे में जाने के लिए बहुत अनिच्छुक हूं। –

उत्तर

3

रूपांतरण विधि खोजने के लिए प्रतिबिंब का उपयोग करने के लिए यहां an example है। तो यदि आप अपने तरीके से उस विधि को प्राप्त कर सकते हैं और अपना स्वयं का रूपांतरण कर सकते हैं। http://bytes.com/topic/c-sharp/answers/903775-getting-operators-using-reflection

//EndType is the type I want to PRODUCE 
//StartType is the type I am pulling data FROM 
MethodInfo mi = EndType.GetMethod(
    "op_Implicit", 
    (BindingFlags.Public | BindingFlags.Static), 
    null, 
    new Type[] { StartType }, 
    new ParameterModifier[0] 
); 
//Now if mi is NOT null, it means there is an operator that allows for converting StartType to EndType, if it is null, there isn't one 
2

कास्टिंग संकलन समय है, जो अपने मामले में Array.SetValue प्रकार object की है जो करने के लिए पहले पैरामीटर के प्रकार पर पर विचार करना होगा पर हल हो गई है, 0 टाइप करने के लिए object डाली हो जाएगा (यानी। बॉक्स्ड)।

क्या कोई कारण है कि आपको प्रतिबिंब का उपयोग करने की आवश्यकता है? जैसा कि अन्य ने पोस्ट किया है आप जेनरिक के साथ ऐसा कर सकते हैं।

यहाँ अपने प्रतिबिंब कोड की एक सन्निकटन जेनरिक का उपयोग कर

private T[] createAndFillArray<T>(T val) 
{ 
    T[] array = new T[1]; 
    array[0] = val; 
    return array;  
} 

रूप

Array arrA = createAndFillArray<A>(exampleA); 
Array arrB = createAndFillArray<B>(exampleB); 

इस प्रकार है जो तुम फोन कर सकते हैं अपनी टिप्पणी के आधार पर एक संभावित क्रियान्वयन हो सकता है

private Array createAndFillArray(Type t, string property, object val) 
{ 
    object element = Activator.CreateInstance(t); 
    PropertyInfo pi = t.GetProperty(property); 
    if (pi != null) 
    { 
    pi.SetValue(element, val, null); 
    } 

    Array arr = Array.CreateInstance(t, 1); 
    arr.SetValue(element, 0); 
    return arr; 
} 

जो आप

के रूप में उपयोग कर सकते हैं
Array arrB = createAndFillArray(t2, "Value", exampleB); 

जहां "वैल्यू" उस लक्ष्य प्रकार में संपत्ति का नाम है जिसे आप सेट करना चाहते हैं।

public static T[] CreateAndFill<T>(params T[] values) 
{ 
    var retval = new T[values.Length]; 
    for (int i = 0; i < values.Length; i++) 
     retval[i] = values[i]; 
    return retval; 
} 

दूसरा, एक कारण है कि अपने निहित डाले काम नहीं कर रहे हो सकता है क्योंकि विधि का उपयोग कर रहे वास्तव में सरणी में मान सेट करने के लिए:

+0

मैं रनटाइम पर प्रतिबिंब द्वारा प्रकार का निर्धारण कर रहा हूं। मेरे पास संपत्ति नाम के लिए एक स्ट्रिंग है, जिसे मैं PropertyInfo pi = myType.getProperty (propertyName) का उपयोग कर रहा हूं। Pi.PropertyType सरणी का प्रकार है जिसे मैं बनाना चाहता हूं। मुझे यकीन नहीं है कि जेनेरिक इस मामले में मदद करेंगे ... –

+0

@sprocketonline, मैं समझता हूं। हमें शायद समस्या के दायरे पर अधिक जानकारी चाहिए। क्या मान हमेशा एक डबल मान होता है, क्या सभी वर्गों में वैल्यू इत्यादि नामक एक संपत्ति होती है क्योंकि आप गतिशील रूप से इंस्टेंस बना सकते हैं, प्रॉपर्टी वैल्यू सेट कर सकते हैं और एंडफाइल में इंस्टेंस को जोड़ सकते हैं ताकि कॉल को एंडफिलएरे बनाने के लिए कॉल किया जा सके, लेकिन अधिक जानकारी है यह समझने की आवश्यकता है कि क्या यह आपकी वास्तविक समस्या या समस्या का असली दायरा है। –

+0

उपरोक्त वास्तविक समस्या का एक बड़ा सरलीकरण है। 'मूल्य' संपत्ति संपत्ति प्रकार किसी भी प्रकार (सभी मूल्य प्रकार, कस्टम वर्ग, बहुत) का हो सकता है और संपत्ति को हमेशा 'मूल्य' के रूप में नहीं जाना जाता है। हालांकि, रूपांतरण के लिए हमेशा सार्वजनिक स्थिर अंतर्निहित ऑपरेटर होना चाहिए, इसलिए मैंने अभी के लिए shf301 के समाधान को लागू करना शुरू कर दिया है। –

0

पहले, जेनरिक सरणी निर्माण तुच्छ होगा एक extern कॉल में समाप्त होता है (किस लाइब्रेरी में मैं प्रतिबिंबक के माध्यम से नहीं बता सकता), जो संभवतः निहित रूपांतरण की जांच नहीं करता है।

0

यह काम करेगा ...

private Array createAndFillArray<T>(object val){ 
    Array arr = Array.CreateInstance(typeof(t), 1); //length 1 in this example only, real-world is of variable length. 
    arr.SetValue((T)val, 0); //this causes the following error: "System.InvalidCastException : Object cannot be stored in an array of this type." 
    return arr; 
} 
+0

यह काम नहीं करेगा क्योंकि एक चीज के लिए जब आप मान को अन-बॉक्स करते हैं तो इसे सटीक उसी प्रकार से अनबॉक्स किया जाना चाहिए, इसलिए एक बॉक्स किए गए डबल को डबल पर अनबॉक्स किया जाना चाहिए, यहां आप ए को टाइप करने के लिए डबल को अनबॉक्स करने का प्रयास करेंगे टाइप बी जो अमान्य है। –

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

  • कोई संबंधित समस्या नहीं^_^