2012-04-22 9 views
9

मैं InitializeComponent के लिए विंडोज फॉर्म डिज़ाइनर की कोड जनरेशन को कस्टमाइज़ करने का प्रयास कर रहा हूं। एमएसडीएन आलेख "Customizing Code Generation in the .NET Framework Visual Designers" में एक अनुभाग "Controlling Code Generation" है जो यह बताता है कि यह कैसे किया जा सकता है इसकी मूल बातें बताती हैं।मैं InitializeComponent की कोड जनरेशन को कैसे अनुकूलित कर सकता हूं? अधिक विशेष रूप से, मैं सभी जेनरेट कोड को कैसे प्रोसेस कर सकता हूं?

मैं बारीकी से ऊपर लेख में एक उदाहरण का पालन किया है:

[DesignerSerializer(typeof(SomeFormSerializer), typeof(CodeDomSerializer))] 
class SomeForm : Form { … } 

फार्म डिजाइनर उसके बाद निम्न InitializeComponent कोड उत्पन्न हो सकता है:

//using System.ComponentModel.Design.Serialization; 

class SomeFormSerializer : CodeDomSerializer 
{ 
    public override object Serialize(IDesignerSerializationManager manager, 
            object value) 
    { 
     // first, let the default serializer do its work: 
     var baseSerializer = (CodeDomSerializer)manager.GetSerializer(
          typeof(Form).BaseType, typeof(CodeDomSerializer)); 
     object codeObject = baseSerializer.Serialize(manager, value); 

     // then, modify the generated CodeDOM -- add a comment as the 1st line: 
     if (codeObject is CodeStatementCollection) 
     { 
      var statements = (CodeStatementCollection)codeObject; 
      statements.Insert(0, new CodeCommentStatement("CODEDOM WAS HERE")); 
     } 

     // finally, return the modified CodeDOM: 
     return codeObject; 
    } 
} 

अब मैं इस मेरे प्रपत्र SomeForm को हुक :

private void InitializeComponent() 
{ 
    … /* (general setup code, such as a call to `this.SuspendLayout`) */ 

    // 
    // someButton 
    // 
    … /* (someButton's properties are set) */ 

    // CODEDOM WAS HERE! 
    // 
    // SomeForm 
    // 
    … /* (form's properties are set) */ 

    … /* (general setup code, such as a call to `this.ResumeLayout`) */ 
} 

ध्यान दें कि कॉम // CODEDOM WAS HERE को InitializeComponent में पहली पंक्ति के रूप में नहीं जोड़ा गया था, लेकिन केवल कोड ब्लॉक की पहली पंक्ति के रूप में जो फॉर्म ऑब्जेक्ट के गुणों से संबंधित है।

अगर मुझे पूरी विधि के जेनरेट कोडडॉम को संशोधित करने में सक्षम होना चाहते हैं, तो न केवल मुझे क्या करना होगा, न कि किसी विशिष्ट वस्तु से निपटने वाले हिस्से में?

पृष्ठभूमि: मैं ऐसा क्यों करना चाहता हूं? विंडोज फॉर्म में, यदि कोई डेटा बाध्यकारी के दौरान लचीला मूल्य रूपांतरण चाहता है, तो आमतौर पर किसी विशेष Binding ऑब्जेक्ट की Format और Parse ईवेंट की सदस्यता लेने का सहारा लेना पड़ता है। तो मैं एक विशेष Binding सबक्लास बना रहा हूं (चलिए इसे ConvertingBinding कहते हैं) जो इस प्रक्रिया को थोड़ा सा सरल बनाता है।

अब, मुद्दा यह है कि जब Windows फॉर्म डिज़ाइनर में डेटा बाइंडिंग सेट की जाती है, तो उत्पन्न कोड Binding के उदाहरण बनाता है; हालांकि, मैं चाहता हूं कि डिजाइनर इसके बजाय मेरे विशेष उप-वर्ग को तुरंत चालू करे। मेरा वर्तमान दृष्टिकोण डिजाइनर को पहले कोडडॉम पेड़ बनाने देना है, फिर उस पेड़ पर चलें और के सभी इंस्टेंटेशन को ConvertingBinding के तत्कालता से प्रतिस्थापित करें।

उत्तर

11

आपको दो Form कक्षा बनाने की आवश्यकता है। पहले FormDesignerSerializerAttribute के साथ। दूसरा Form पहले से वंशज है। उसके बाद आप InitializeComponent() को दूसरे Form और उसके नियंत्रण या घटकों के लिए अनुकूलित कर सकते हैं। इसके लिए आपको manager.Context का उपयोग StatementContext और CodeStatementCollection ऑब्जेक्ट्स प्राप्त करने के लिए करना चाहिए जिसमें Form के नियंत्रण क्रमबद्ध कोड शामिल हैं।

यहां कुछ आसान कदम हैं।

using System.CodeDom; 
using System.ComponentModel.Design.Serialization; 
using System.Collections; 

नया फ़ॉर्म बनाएं और जोड़ने DesignerSerializerAttribute:

[DesignerSerializer(typeof(CustomFormSerializer), typeof(CodeDomSerializer))] 
class CustomForm : Form { … } 

CustomForm वंशज बनाएं और उसमें कुछ नियंत्रण या घटकों जोड़ें: के लिए CustomFormSerializer को

class CustomForm1 : CustomForm { … } 

जोड़ें विधि
पुस्तकालयों को शामिल करें प्रसंस्करण CodeStatementCollection, उदाहरण के लिए:

private void DoSomethingWith(CodeStatementCollection statements) 
{ 
    statements.Insert(0, new CodeCommentStatement("CODEDOM WAS HERE")); 
} 

Serialize विधि उपयोग चक्र में manager.Context के माध्यम से:

public override object Serialize(IDesignerSerializationManager manager, 
    object value) 
{ 
    //Cycle through manager.Context    
    for (int iIndex = 0; manager.Context[iIndex] != null; iIndex++) 
    { 
     object context = manager.Context[iIndex]; 

     if (context is StatementContext) 
     // Get CodeStatementCollection objects from StatementContext 
     { 
      ObjectStatementCollection objectStatementCollection = 
       ((StatementContext)context).StatementCollection; 

      // Get each entry in collection. 
      foreach (DictionaryEntry dictionaryEntry in objectStatementCollection) 
       // dictionaryEntry.Key is control or component contained in CustomForm descendant class 
       // dictionartEntry.Value is CodeDOM for this control or component 
       if (dictionaryEntry.Value is CodeStatementCollection) 
        DoSomethingWith((CodeStatementCollection)dictionaryEntry.Value); 
     } 

     //Do something with each collection in manager.Context: 
     if (context is CodeStatementCollection) 
      DoSomethingWith((CodeStatementCollection)context); 
    } 

    // Let the default serializer do its work: 
    CodeDomSerializer baseClassSerializer = (CodeDomSerializer)manager. 
     GetSerializer(value.GetType().BaseType, typeof(CodeDomSerializer)); 
    object codeObject = baseClassSerializer.Serialize(manager, value); 

    // Then, modify the generated CodeDOM: 
    if (codeObject is CodeStatementCollection) 
     DoSomethingWith((CodeStatementCollection)codeObject); 

    // Finally, return the modified CodeDOM: 
    return codeObject; 
} 
+0

यह लगभग है कि मैं क्या चाहता हूँ। यह 'बाध्यकारी' उदाहरणों को प्रतिस्थापित करने के लिए पर्याप्त लगता है; लेकिन मैं अभी भी पूरी विधि तक नहीं पहुंच सकता, यानी 'शुरुआती कॉम्पोनेंट' में पहली कुछ पंक्तियां और अंतिम कुछ पंक्तियां। – stakx

+1

@stakx: 'InitializeComponent' में पहली कुछ पंक्तियां हमेशा' CodeVariableDeclarationStatement' ऑब्जेक्ट्स 'से मिलती हैं। यदि आप इनमें से किसी भी ऑब्जेक्ट में 'CodeStatementCollection' में परिवर्तन करते हैं या संग्रह में नया' CodeVariableDeclarationStatement' जोड़ते हैं, तो ये सभी परिवर्तन पहली कुछ पंक्तियों में दिखाई देंगे। किसी अन्य 'CodeStatement' लाइनें सभी' CodeVariableDeclarationStatement' लाइनों के बाद दिखाई देंगी। – nempoBu4

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