2009-06-17 12 views
11

मैं वर्तमान में सी # में प्रतिबिंब का उपयोग कर सामान्य वस्तुओं को एक्सएमएल में सहेजने के लिए कुछ कोड लिख रहा हूं।सी # संरचना बनाने के लिए प्रतिबिंब का उपयोग

समस्या यह है कि कुछ ऑब्जेक्ट्स में एक्सएमएल को वापस पढ़ने पर structs हैं और मैं संरचना शुरू करने के तरीके को कैसे काम नहीं कर सकता। एक वर्ग के लिए मैं उपयोग कर सकते हैं

ConstructorInfo constructor = SomeClass.GetConstructor(Type.EmptyTypes); 

तथापि, एक struct के लिए, वहाँ कोई निर्माता तो उपरोक्त कोड सेट निर्माता शून्य पर जो कोई पैरामीटर लेता है। मैंने

SomeStruct.TypeInitializer.Invoke(null) 

पर भी प्रयास किया लेकिन यह सदस्य-अभिगम्यता को फेंक देता है। Google कोई आशाजनक हिट नहीं देता है। किसी भी सहायता की सराहना की जाएगी।

उत्तर

14

यदि मान स्ट्रक्चर हैं, तो वे अप्रत्याशित होने के लिए हैं - इसलिए आप पैरामीटर रहित कन्स्ट्रक्टर को कॉल नहीं करना चाहते हैं, लेकिन वह जो कन्स्ट्रक्टर तर्क के रूप में उपयुक्त मान लेता है।

structs नहीं अपरिवर्तनीय है, तो उनसे दूर जितनी जल्दी संभव हो, बना रहेगा यदि आप कर सकते हैं ... लेकिन अगर आप पूरी तरह से है ऐसा करने के लिए, तो Activator.CreateInstance(SomeClass) का उपयोग कर रहे हैं। जब आप मूल्य प्रकार पर गुण या फ़ील्ड सेट करने के प्रतिबिंब का उपयोग करते हैं तो आपको बहुत सावधान रहना होगा - उस देखभाल के बिना, आप एक प्रतिलिपि बनाकर, उस प्रतिलिपि पर मूल्य बदलकर, और फिर उसे फेंक देंगे। मैं संदेह है कि अगर आप एक बॉक्स्ड संस्करण के साथ भर में काम करते हैं, आप ठीक हो जाएगा:

using System; 

// Mutable structs - just say no... 
public struct Foo 
{ 
    public string Text { get; set; } 
} 

public class Test 
{ 
    static void Main() 
    { 
     Type type = typeof(Foo); 

     object value = Activator.CreateInstance(type); 
     var property = type.GetProperty("Text"); 
     property.SetValue(value, "hello", null); 

     Foo foo = (Foo) value; 
     Console.WriteLine(foo.Text); 
    } 
} 
+0

महाकाव्य धागे में पोस्टिंग ... इसके अलावा, संक्षेप में, साफ जवाब के लिए ऊपर उठाना। –

+0

समस्या यह है कि अभी, एक्टिवेटर। क्रिएटइंस्टेंस जिस प्रकार के लिए मैंने पूछा था उसके बजाए एक रनटाइम टाइप देता है :(जिसका मतलब है कि गेटफिल्ड्स कुछ भी नहीं लौटाता है। –

+0

@ मार्सल: लगता है जैसे आपको एक [mcve] के साथ एक नया प्रश्न पूछना चाहिए। –

1

बस जोड़ने के लिए - अपरिवर्तनीय structs के साथ, आप निर्माता के लिए पैरामीटर मिलान करना है की संभावना है। दुर्भाग्यवश यह मुश्किल है जब कई संरचनाएं हो सकती हैं, और विशेष रूप से कुछ प्रकार के सार्वजनिक कन्स्ट्रक्टर की बजाय एक अलग स्थिर "बनाएं" विधि होती है। लेकिन आप मिलान किया है यह सोचते हैं, तब भी आप Activator.CreateInstance उपयोग कर सकते हैं:

Type type = typeof(Padding); // just an example 
    object[] args = new object[] {1,2,3,4}; 
    object obj = Activator.CreateInstance(type, args); 

हालांकि - कोड एक निर्माता लेने के लिए (ऊपर 3 है ...) आसान नहीं है। आप कह सकते हैं "सबसे जटिल लेने" और फिर संपत्ति के नाम (केस असंवेदी) पैरामीटर नाम से मेल करने का प्रयास ...

एक भोली उदाहरण:

static void Main() { 
    Dictionary<string, object> propertyBag = 
     new Dictionary<string, object>(); 
    // these are the values from your xml 
    propertyBag["Left"] = 1; 
    propertyBag["Top"] = 2; 
    propertyBag["Right"] = 3; 
    propertyBag["Bottom"] = 4; 
    // the type to create 
    Type type = typeof(Padding); 

    object obj = CreateObject(type, propertyBag); 

} 
static object CreateObject(Type type, IDictionary<string,object> propertyBag) 
{ 
    ConstructorInfo[] ctors = type.GetConstructors(); 
    // clone the property bag and make it case insensitive 
    propertyBag = new Dictionary<string, object>(
     propertyBag, StringComparer.OrdinalIgnoreCase); 
    ConstructorInfo bestCtor = null; 
    ParameterInfo[] bestParams = null; 
    for (int i = 0; i < ctors.Length; i++) 
    { 
     ParameterInfo[] ctorParams = ctors[i].GetParameters(); 
     if (bestCtor == null || ctorParams.Length > bestParams.Length) 
     { 
      bestCtor = ctors[i]; 
      bestParams = ctorParams; 
     } 
    } 
    if (bestCtor == null) throw new InvalidOperationException(
     "Cannot create - no constructor"); 
    object[] args = new object[bestParams.Length]; 
    for (int i = 0; i < bestParams.Length; i++) 
    { 
     args[i] = propertyBag[bestParams[i].Name]; 
     propertyBag.Remove(bestParams[i].Name); 
    } 
    object obj = bestCtor.Invoke(args); 
    // TODO: if we wanted, we could apply any unused keys in propertyBag 
    // at this point via properties 
    return obj; 
} 
2

CreateInstance कोई साथ structs के साथ मदद नहीं करेगा स्पष्ट रूप से परिभाषित रचनाकार।

FormatterServices.GetUninitializedObject(Type type); 

यह रिक्त structs के साथ चाल है।

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