2013-01-16 13 views
8
  • वहाँ एक रास्ता इतना है कि यह का कोई उदाहरण एक क्षेत्र में संग्रहित किया जा सकता (TypedReference और ArgIterator करने के लिए एक समान तरीके से) एक प्रकार (या और भी बेहतर, एक अंतरफलक) चिह्नित करने के लिए है?
  • इसी तरह, अज्ञात तरीकों से गुजरने के उदाहरणों को रोकने के लिए कोई तरीका है - और सामान्य रूप से - उपर्युक्त दो प्रकार के व्यवहार की नकल करने के लिए?
  • क्या यह आईएलडीएएम के माध्यम से या अधिक आम तौर पर आईएल संपादन के माध्यम से किया जा सकता है? चूंकि UnconstrainedMelody एक संकलित असेंबली के द्विआधारी संपादन के माध्यम से सामान्य रूप से अनुपयोगी परिणाम प्राप्त करता है, हो सकता है कि एक ही दृष्टिकोण के माध्यम से कुछ प्रकार (या यहां तक ​​कि बेहतर, सार तत्व या मार्कर इंटरफेस) को "चिह्नित" करने का एक तरीका हो।

मुझे शक है यह संकलक में hardcoded क्योंकि documentation for the error CS0610 कहता है:मेक प्रकार के उदाहरणों गैर संग्रहणीय

कुछ प्रकार है कि खेतों या गुण के रूप में इस्तेमाल नहीं किया जा सकता है। इन प्रकारों में शामिल हैं ...

मेरी राय में संकेत मिलता है कि उन प्रकारों के सेट को बढ़ाया जा सकता है - लेकिन मैं गलत हो सकता था।

मैंने एसओ पर थोड़ी सी खोज की है और जब मैं समझता हूं कि throwing a compiler error प्रोग्रामेटिक रूप से नहीं किया जा सकता है, तो मुझे कोई स्रोत नहीं मिला कि कुछ "विशेष" प्रकार के व्यवहार दोहराए जा सकते हैं।

भले ही प्रश्न अधिकतर अकादमिक है, फिर भी उत्तर के लिए कुछ उपयोग हो सकते हैं। उदाहरण के लिए, कभी-कभी यह सुनिश्चित करने के लिए उपयोगी हो सकता है कि एक निश्चित वस्तु का जीवनकाल उस विधि ब्लॉक को बाध्य कर देता है जो इसे बनाता है।

संपादित करें:RuntimeArgumentHandle एक और (अनियमित) गैर-स्तरीय प्रकार है।

संपादित करें 2: यह किसी भी काम का हो सकता है, तो ऐसा लगता है कि CLR अभी भी यह सोचते हैं कि प्रकार के कोई रास्ता नहीं दूसरों से अलग कर रहे हैं और साथ ही एक अलग तरीके से उन प्रकार के व्यवहार करता है, अगर न केवल संकलक ()। उदाहरण के लिए, निम्न प्रोग्राम TypeLoadExceptionTypedReference* के बारे में फेंक देगा। मैंने इसे कम करने के लिए इसे अनुकूलित किया है लेकिन आप जो कुछ भी चाहते हैं उसके आसपास काम कर सकते हैं। पॉइंटर के प्रकार को बदलने के लिए, कहें, void* अपवाद फेंक नहीं देगा।

using System; 

unsafe static class Program 
{ 
    static TypedReference* _tr; 

    static void Main(string[] args) 
    { 
     _tr = (TypedReference*) IntPtr.Zero; 
    } 
} 
+5

अगर मैं * हार्ड-कोडेड, बीटीडब्ल्यू था तो मुझे आश्चर्य नहीं होगा। सिर्फ इसलिए कि प्रलेखन इसे पिन करना नहीं चाहता है इसका मतलब यह नहीं है कि यह संकलक में किया गया तरीका नहीं है। –

+0

मुझे एक ही चीज़ लगता है, लेकिन मुझे जांच करनी होगी। –

+1

[CS0611] (http://msdn.microsoft.com/en-US/library/bfca7x6z (v = vs.80) .aspx) एक संबंधित त्रुटि है, हालांकि शायद दोनों का समाधान दोनों पर लागू होगा। – Mir

उत्तर

5

ठीक है। यह काफी पूर्ण विश्लेषण नहीं है, लेकिन मुझे संदेह है कि यह निर्धारित करने के प्रयोजनों के लिए पर्याप्त है कि आप यह कर सकते हैं, यहां तक ​​कि आईएल को झुकाकर भी - जहां तक ​​मैं कह सकता हूं, आप नहीं कर सकते।

मैं भी dotPeek साथ decompiled संस्करण को देख पर, न कि किसी विशेष उस विशेष प्रकार/वहाँ में उन विशेष प्रकार, विशेषता के लिहाज से या अन्यथा के बारे में देख सकते हैं:

namespace System 
{ 
    /// <summary> 
    /// Describes objects that contain both a managed pointer to a location and a runtime representation of the type that may be stored at that location. 
    /// </summary> 
    /// <filterpriority>2</filterpriority> 
    [ComVisible(true)] 
    [CLSCompliant(false)] 
    public struct TypedReference 
    { 

तो, जिसमें हो

namespace NonStorableTest 
{ 
    //public class Invalid 
    //{ 
    // public TypedReference i; 
    //} 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("EmitNonStorable"), 
                         AssemblyBuilderAccess.RunAndSave); 

      ModuleBuilder moduleBuilder = asmBuilder.DefineDynamicModule("EmitNonStorable", "EmitNonStorable.dll"); 

      TypeBuilder invalidBuilder = moduleBuilder.DefineType("EmitNonStorable.Invalid", 
                    TypeAttributes.Class | TypeAttributes.Public); 

      ConstructorBuilder constructorBuilder = invalidBuilder.DefineDefaultConstructor(MethodAttributes.Public); 

      FieldBuilder fieldI = invalidBuilder.DefineField("i", typeof (TypedReference), FieldAttributes.Public); 

      invalidBuilder.CreateType(); 
      asmBuilder.Save("EmitNonStorable.dll"); 

      Console.ReadLine(); 
     } 
    } 
} 

यही कारण है, जब आप इसे चलाने के लिए, एक TypeLoadException, जिनमें से स्टैक ट्रेस आप System.Reflection.Emit.TypeBuilder.TermCreateClass के लिए अंक फेंकता है:, मैं इस तरह के एक वर्ग System.Reflection.Emit का उपयोग कर बनाने की कोशिश की।

[SuppressUnmanagedCodeSecurity] 
[SecurityCritical] 
[DllImport("QCall", CharSet = CharSet.Unicode)] 
private static void TermCreateClass(RuntimeModule module, int tk, ObjectHandleOnStack type); 

CLR का अप्रबंधित भागों में ओर इशारा करते हुए: तो फिर मैं decompiler है, जो मुझे यह दिया साथ उस के बाद चला गया। इस बिंदु पर, हारने के लिए नहीं, मैंने सीएलआर के संदर्भ संस्करण के लिए साझा स्रोतों में खोला। मैं इस तर्क के माध्यम से सभी उचित उपयोग से परे इस जवाब को फलने से बचने के लिए नहीं करूँगा, लेकिन आखिरकार, आप \ clr \ src \ vm \ class.cpp में विधिTableBuilder :: SetupMethodTable2 फ़ंक्शन में समाप्त हो जाते हैं (

// Mark the special types that have embeded stack poitners in them 
         if (strcmp(name, "ArgIterator") == 0 || strcmp(name, "RuntimeArgumentHandle") == 0) 
          pClass->SetContainsStackPtr(); 

और

if (pMT->GetInternalCorElementType() == ELEMENT_TYPE_TYPEDBYREF) 
          pClass->SetContainsStackPtr(); 

यह बाद \ src \ इंक \ cortypeinfo.h में पाया जानकारी से संबंधित इस प्रकार,: जो भी क्षेत्र वर्णनकर्ता) जहां इन पंक्तियों को खोजने के सेट करने के लिए, प्रकट होता है

// This describes information about the COM+ primitive types 

// TYPEINFO(enumName,    className,   size,   gcType,   isArray,isPrim, isFloat,isModifier) 

[...] 

TYPEINFO(ELEMENT_TYPE_TYPEDBYREF, "System", "TypedReference",2*sizeof(void*), TYPE_GC_BYREF, false, false, false, false) 

(यह वास्तव में उस सूची में एकमात्र ELEMENT_TYPE_TYPEDBYREF प्रकार है।)

ContainsStackPtr() तब बदले में उन स्थानों को उपयोग करने से रोकने के लिए विभिन्न स्थानों में कहीं और इस्तेमाल किया जाता है, जिसमें फ़ील्ड समेत \ src \ vm \ class से। सीपी, MethodTableBuilder :: InitializeFieldDescs():

// If it is an illegal type, say so 
if (pByValueClass->ContainsStackPtr()) 
{ 
    BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil); 
} 
वैसे भी

: काफी लंबे, लंबे समय से कहानी कम कटौती करने के लिए है, यह मामला है कि जो प्रकार इस तरह से गैर संग्रहणीय हैं प्रभावी रूप से कड़ी मेहनत है होना करने के लिए प्रतीत होता है सीएलआर में कोडित, और इस प्रकार यदि आप सूची बदलना चाहते हैं या आईएल प्रदान करना चाहते हैं तो प्रकारों को गैर-स्मारक के रूप में ध्वजांकित करना है, तो आपको मोनो या साझा स्रोत सीएलआर लेने और अपने स्पिन को दूर करने के लिए बहुत कुछ करना होगा स्वयं बनाम एन।

+1

महान जवाब, मुझे लगता है कि यह सुलझता है। – Mir

2

मुझे आईएल में कुछ भी नहीं मिला जो संकेत दिया कि उन प्रकार किसी भी तरह से विशेष हैं। मुझे पता है कि कंपाइलर में कई, कई विशेष मामले हैं, जैसे int/Int32 को आंतरिक प्रकार int32, या Nullable संरचना से संबंधित कई चीज़ों में परिवर्तित करना। मुझे अत्यधिक संदेह है कि इन प्रकार के विशेष मामले भी हैं।

एक संभावित समाधान Roslyn होगा, जो मुझे उम्मीद है कि आप इस तरह की बाधा उत्पन्न करेंगे।

+0

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

+0

@Eve मुझे लगता है कि यदि आप इस तरह के रूप में दुर्लभ कुछ कर रहे हैं, तो आप बिना किसी समस्या के Roslyn का उपयोग करने में सक्षम होंगे। बेशक, यदि यह एक सार्वजनिक प्रकार है, तो आप ऐसा करने में सक्षम नहीं हो सकते हैं। –

+0

आपको लगता है कि Roslyn वास्तव में कैसे मदद करेगा? – svick

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