2012-01-01 12 views
7

मैं एक ऐसी प्रणाली बना रहा हूं जो एक छोटी स्क्रिप्ट को एक डीएल में बदल देता है। मुझे एक समस्या का सामना करना पड़ रहा है जब मैं एक शून्य मूल्य वर्ग लेने की कोशिश करता हूं और इसे पैरामीटर का डिफ़ॉल्ट मान बना देता हूं। समस्या यह है कि मुझे कंपाइलर के भीतर चयनित उपयोगकर्ता का एक उदाहरण बनाने की आवश्यकता है और इसे स्थिर के रूप में सेट करें।एक्टिवेटर के माध्यम से एक नलिका ऑब्जेक्ट बनाना। क्रिएट इंस्टेंस रिटर्न शून्य

दुर्भाग्य से, जब भी मैं का उपयोग Activator.CreateInstance(NullableType) मैं null वापसी मान के रूप में मिलता है (जहां NullableType उपयोगकर्ता इनपुट से एक बनाया प्रकार है)। उदाहरण के लिए, बस निष्पादित:

object Test = Activator.CreateInstance(typeof(Nullable<int>)); 
Console.WriteLine(Test == null); 

सत्य लौटाता है। यह केवल न्यूलबल्स के साथ होता है। सी # में निर्मित एक संरचना, यहां तक ​​कि एक सामान्य, ठीक बनाया गया है। बिल्ली, अगर मैं & कॉपी करता हूं तो DotNetReflector (और TypeDependencyAttribute, TargetPatchingOptOutAttribute, और ThrowHelper कॉल को हटाएं क्योंकि मुझे उन तक पहुंच नहीं है), यह ऊपर झूठा दिखाता है।

क्या चल रहा है? क्या मुझे रन-टाइम तक जेनेरिक पैरामीटर नहीं पता जब कोई नामुमकिन बनाने का कोई अन्य संभावित तरीका है?

उत्तर

1

समस्या ParameterBuilder.SetConstant में है, Activator.CreateInstance नहीं है। SetConstant वैकल्पिक पैरामीटर के डिफ़ॉल्ट मान को परिभाषित करने के लिए एक फ़ंक्शन है, और निरंतर के रूप में एक ठोस मूल्य प्रदान किया जाना आवश्यक है। रेफ क्लास के लिए, null एक वैध ठोस मूल्य है, लेकिन Nullable<> के निर्माण से पहले मूल्य वर्गों के लिए, null मान्य मान नहीं था। उदाहरण के लिए, int में null को अनबॉक्स कैसे करें? तो SetConstant जांच मूल्यों को देखने के लिए कि क्या ठोस मूल्य null था और ArgumentException को NullReferenceException की तुलना में अधिक वर्णनात्मक त्रुटि के रूप में फेंक दिया गया है, तो आप मान वर्ग में शून्य को अनबॉक्स करने के लिए प्राप्त करेंगे।

Nullable<> के मामले में, null अब मूल्य वर्ग के लिए एक वैध ठोस मूल्य है। Nullable<> स्वयं एक मूल्य वर्ग है, जैसा कि Activator.CreateInstance के साथ देखा गया है, और को Nullable<int> में अनबॉक्सिंग का अर्थ है। यह वह जगह है जहां SetConstant में एक बग है: यह इसे ध्यान में रखने में विफल रहता है और वास्तव में एक त्रुटि नहीं है के लिए 'वर्णनात्मक' त्रुटि फेंकता है। माइक्रोसॉफ्ट से बगफिक्स के बदले, SetConstant पर किसी भी कॉल को शून्य Nullable<> के साथ गलत सशर्त द्वारा संरक्षित व्यवहार को लागू करना होगा। इसका मतलब प्रतिबिंब का उपयोग कर ParameterBuilder की निजी विधियों और फ़ील्ड में खोदना है। इस मामले में मैंने को केवल को संभालने के लिए कोड बनाया है। मानक SetConstant फ़ंक्शन का उपयोग उन परिस्थितियों में किया जाना चाहिए जो बग प्रकट नहीं करते हैं।

//ModuleBuilder module : a parameter passed into the containing function, the module which is being built (which contains the method that has the optional parameter we are setting the constant for) 
//ParameterBuilder optParam : A parameter passed into the containing function, the parameter that is being built which is to have the null default value. 
MethodInfo method = typeof(TypeBuilder).GetMethods(BindingFlags.Static | BindingFlags.NonPublic) 
    .Where(m => m.Name == "SetConstantValue" && m.GetParameters().Length > 0 && m.GetParameters()[0].ParameterType.Name == "RuntimeModule") 
    .Single(); 
var RuntimeHandle = typeof(ModuleBuilder).GetMethod("GetNativeHandle", BindingFlags.NonPublic | BindingFlags.Instance); 
method.Invoke(null, new object[] 
{ 
    RuntimeHandle.Invoke(module, new object[]{}), 
    optParam.GetToken().Token, 
    0x12, 
    null 
}); 

मैंने माइक्रोसॉफ्ट को बग की सूचना दी है।उन्होंने जवाब दिया कि यह .NET 3.5 में तय नहीं किया जाएगा, लेकिन यह आंतरिक बग डेटाबेस में जोड़ा गया था।

अद्यतन:

बग .NET 4.0 में निर्धारित किया गया है। ParameterBuilder.SetConstant में अब constant == null सशर्त की एक शाखा है जो यह देखने के लिए जांचती है कि कोई मान प्रकार Nullable<> से व्युत्पन्न सामान्य है या नहीं, और केवल अपवाद फेंकता है।

+0

मॉड्यूल और ऑप्टपैम का क्या संदर्भ है? –

+0

1. बहुत पागल हैक। 2. नलिकाएं ऑब्जेक्ट फॉर्म में शून्य हैं - यह डिज़ाइन द्वारा है। 3. कृपया अधिक जानकारी कृपया। – Vlad

+0

हां, यह एक पागल हैक है। यह 'पैरामीटरबिल्डर। सैटकॉन्स्टेंट 'के आसपास काम करना था, यदि' if (value == null) नया ArgumentException (...) 'फेंक रहा है। वास्तविक देशी कोड जो 'पैरामीटरबिल्डर .etConstant' उपयोग करता है (जो निजी है और जो मैं ऊपर के लिए प्रतिबिंबित कर रहा हूं) ठीक है, नलबल्स शून्य के साथ ठीक है, क्योंकि यह डिज़ाइन द्वारा है। यह केवल प्रबंधित, सार्वजनिक सामना करने वाला फ़ंक्शन था जिसमें एक बग था, और बाईपासिंग की आवश्यकता थी। बग को तब से तय कर दिया गया है, इसलिए जब तक आप 3.5 या उससे कम लक्ष्यीकरण नहीं कर रहे हैं, तो यह उत्तर अब आवश्यक नहीं है। –

6

this MSDN blog से:

Activator.CreateInstance कभी नहीं अशक्त वापसी की उम्मीद की जा सकती है से पहले; इस डीसीआर के साथ, प्रकार के उदाहरण को बनाते समय यह शून्य हो जाएगा लेकिन गैर-शून्य टी मान प्रदान नहीं करेगा। उदाहरण के लिए, एक्टिवेटर। क्रिएट इंस्टेंस (टाइपऑफ (Int32?)) शून्य देता है।

समस्या को ब्लॉग पोस्ट द्वारा समझाए गए अनुसार Nullable<T> के चर के साथ क्या करना है।

+0

यह मेरे दो प्रश्नों में से एक का उत्तर देता है। साथ ही, मुझे एमएसडीएन आलेख के माध्यम से आपका देखने से कुछ मिनट पहले यह जवाब मिला: http://msdn.microsoft.com/en-us/library/ms228597.aspx। वह पत्तियां: मैं रनटाइम तक अपने पैरामीटर को जानने के बिना एक नामुमकिन कैसे बना सकता हूं, और इसे पैरामीटरबिल्डर .etConstant पर पास कर सकता हूं? यहां तक ​​कि सेटकंटस्टेंट के लिए एक शून्य शून्य करने के लिए भी ब्लॉग और एमएसडीएन लेख में उद्धृत कारणों के लिए विफल रहता है। –

+0

मैं अपने शोध में एक समान प्रश्न पर ठोकर खाई। हालांकि उनकी स्थिति थोड़ा अलग है: http://stackoverflow.com/questions/1488706/set-property-nullable-by-reflection –

+0

मुझे नहीं पता कि यह आपके दूसरे प्रश्न का उत्तर देगा, लेकिन आप गतिशील रूप से अपना सामान्य प्रकार बना सकते हैं रिफ्लेक्शन (http://stackoverflow.com/questions/2078914/c-sharp-dynamic-generic-type) का उपयोग करके अपनी आवश्यकताओं के आधार पर रनटाइम पर और परिणामी गतिशील प्रकार को 'Activator.CreateInstance' पर अपने प्रश्न में दिखाए जाने पर पास करें। मुझे वास्तव में अनुभव है कि अगर आपको मदद की ज़रूरत है तो कृपया हमें बताएं। –

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

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