2010-08-31 18 views
11

मैं समझने की कोशिश कर रहा हूं कि निम्न कोड अपेक्षित के रूप में क्यों काम नहीं कर रहा है; TypeDescriptor बस गुणों से कस्टम कनवर्टर नहीं उठा रहा है। मैं केवल यह मान सकता हूं कि मैंने एक स्पष्ट गलती की है लेकिन मैं इसे नहीं देख सकता।यह टाइप कनवर्टर क्यों काम नहीं कर रहा है?

- संपादन - इस कोड को जब मैं अपने आप ही एक कंसोल में इसे चलाने, मैं वास्तव में एक और अधिक जटिल आवेदन के भीतर से और एक अलग नाम स्थान से एक कनवर्टर फोन कर रहा हूँ काम करने के लिए लगता है।

- संपादन - मैं कैसे TypeDescriptor डिबग तो मैं देख सकते हैं कि क्या हो रहा है और उसके बाद मैं शायद यह अपने आप जवाब कर सकते हैं कर सकते हैं पर वैकल्पिक रूप से किसी भी सुझाव।

- संपादित करें - यह समस्या लगभग निश्चित रूप से विभिन्न असेंबली में होने वाले टुकड़ों से संबंधित है।

- संपादन - ऐसा लगता है कि इस गतिशील रूप से लोड हो रहा है विधानसभाओं के कुछ मोड़ की वजह से काम नहीं कर रहा है - इस कोड वास्तुकला की तरह एक प्लगइन के तहत चल रहा है।

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 
using System.ComponentModel; 

namespace MyTest 
{ 

    public class TestTester 
    { 
     public static void Main(string[] args) 
     { 
      object v = TypeDescriptor.GetConverter(typeof(MyTest.Test)).ConvertFromInvariantString("Test"); 
     } 
    } 

    public class TestConverter : TypeConverter 
    { 

     public override bool GetStandardValuesSupported(ITypeDescriptorContext context) 
     { 
      return false; 
     } 

     public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType) 
     { 
      if (sourceType == typeof(string) || base.CanConvertFrom(context, sourceType)) 
      { 
       return true; 
      } 
      return base.CanConvertFrom(context, sourceType); 
     } 

     public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
     { 
      if (destinationType == typeof(Test) || base.CanConvertTo(destinationType)) 
      { 
       return true; 
      } 
      return base.CanConvertTo(context, destinationType); 
     } 

     public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
     { 
      if (value.GetType() == typeof(string)) 
      { 
       Test t = new Test(); 
       t.TestMember = value as string; 
       return t; 
      } 
      return base.ConvertFrom(context, culture, value); 
     } 

     public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) 
     { 
      if (destinationType == typeof(string) && value.GetType() == typeof(Test)) 
      { 
       return ((Test)value).TestMember; 
      } 
      return base.ConvertTo(context, culture, value, destinationType); 
     } 

    } 

    [TypeConverterAttribute(typeof(TestConverter))] 
    public struct Test 
    { 
     public string TestMember { get; set; } 
    } 
} 

उत्तर

1

मैंने मामलों को देखा है, जहां मैं अन्य असेंबली से आंतरिक क्षेत्रों पर विशेषताओं को पिकअप नहीं कर सका। सुनिश्चित नहीं है कि यह एक .NET बग था या यदि यह तय किया गया है।

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

+0

मुझे लगता है कि यह अलग-अलग असेंबली में होने की संभावना है - मैंने बस बिट्स को चारों ओर ले जाने की कोशिश की थी; जब मेरे पास एक संपत्ति असेंबली में किसी अन्य असेंबली में आइटम का जिक्र किया गया था तो यह संपत्ति को प्रदर्शित करने के लिए अपने टाइपकॉन्टर एट अल का उपयोग नहीं कर सका। अगर इस पर कोई समाधान नहीं था तो मुझे आश्चर्य होगा। – cyborg

10

मैं भी इस समस्या थी और समस्या के लिए एक समाधान के वर्तमान आवेदन डोमेन के AssemblyResolve घटना की सदस्यता और मैन्युअल रूप से विधानसभा को हल करने के लिए है।

यह एक अच्छा समाधान से बहुत दूर है, लेकिन ऐसा लगता है कि यह काम करता है। मुझे नहीं पता कि ढांचा इस तरह से क्यों व्यवहार करता है। मैं वास्तव में इस समस्या को हल करने के लिए एक कम हैकिश तरीका खोजना चाहता हूं।

public void DoMagic() 
{ 
    // NOTE: After this, you can use your typeconverter. 
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 
} 

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    AppDomain domain = (AppDomain)sender; 
    foreach (Assembly asm in domain.GetAssemblies()) 
    { 
     if (asm.FullName == args.Name) 
     { 
      return asm; 
     } 
    } 
    return null; 
} 
1

यह एक छोटा सा देर हो चुकी है, लेकिन इस मुद्दे पर दिखाई दिया जब मैं एक TypeConverter है कि एक और विधानसभा जो सीधे निष्पादन विधानसभा द्वारा संदर्भित नहीं है में रहते हैं के लिए कहा।

0

हमने इस व्यवहार को प्लगबेस सिस्टम में भी देखा है जिसमें एपबेस फ़ोल्डर के बाहर से असेंबली लोड करना शामिल है।

सभी बुराइयों की जड़ TypeDescriptorAttribute कार्यान्वयन में एक दोष है।

विशेषता में दो कन्स्ट्रक्टर ओवरलोड हैं, एक सादे टेक्स्ट प्रकार विनिर्देश (जो अनपेक्षित रूप से - रनटाइम पर शुद्ध जादू नहीं है) और एक प्रारंभिक बाध्य typeof() संदर्भ के लिए है। यदि आप दूसरे पथ का उपयोग करते हैं, तो संभवतः गलत क्या हो सकता है? खैर, वास्तव में विशेषता केवल पहले पथ का उपयोग करती है। असली और सही रनटाइम प्रकार संदर्भ सादे टेक्स्ट में फ़्लैटन किया गया है, और यहां ड्रैगन हैं। तो यह typeof() लिखने का कोई उपयोग नहीं है - यह हमेशा सादा पाठ और जादू परिदृश्य है।

समाधान? कोई आदर्श नहीं, लेकिन हमारे मामले में हम केवल हमारे सिस्टम के भीतर प्रकार के रूपांतरणों का उपभोग कर रहे थे, इसलिए हमने इसके बजाय ValueSerializerAttribute चुना। जो मूल रूप से एक ही सामान करने का डब्ल्यूपीएफ का तरीका है। इसका कार्यान्वयन typeof().ctor ओवरलोड के आसपास सही है जिसमें यह प्रारंभिक बाध्य प्रकार की पहचान को संरक्षित करने में सफल होता है और हमेशा कोड में लिखे गए सही प्रकार को लोड करता है।

यदि आप सिस्टम कनवर्टर का उपयोग करने के लिए सिस्टम (या WinForms) कोड चाहते हैं, तो इससे मदद नहीं मिलेगी।

+0

आपके समाधान का प्रयास किया और यह WPF के लिए काम नहीं करता है। –

+0

सुनिश्चित करें कि इस डीएलएल से उस प्रकार के एक डीएलएल संदर्भ में है - इसे संकलित करने के बाद, न केवल प्रोजेक्ट में। या Roslyn का उपयोग करने वाले एक नए कंपाइलर संस्करण के साथ संकलित करें, यह मूल की तरह डीएलएल संदर्भों को भूत नहीं करता है। – hypersw

0

The answer to this other question यहां लागू होना चाहिए। AssemblyResolve की सदस्यता लेने से यह एक बहुत ही सरल समाधान है।

संक्षेप में, क्लास नाम प्रदान करने के लिए typeof का उपयोग करने के बजाय, प्रकार कनवर्टर क्लास के पूर्ण स्ट्रिंग नाम का उपयोग करके TypeConverter विशेषता सेट करना है।

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