2015-01-08 5 views
8

के साथ अर्थपूर्ण कोड उत्पन्न करना हम Roslyn के साथ कोड उत्पन्न करने का तरीका जानने का प्रयास करते हैं। मैं CSharpSyntaxTree.ParseText जैसे कुछ के बारे में बात नहीं कर रहा हूं जो कुछ तारों को ले जाएगा और उन्हें एएसटी में परिवर्तित करेगा। इसके बजाय, मैं इस (छद्म कोड) की तरह किसी भी तरह अपने मॉडल का निर्माण करना चाहते हैं:रोसलीन

  1. संकलन इकाई के रूप में file बनाएं
  2. जोड़े वर्ग MyClassfile विधि जोड़ने के लिए
  3. DoSomethingMyClass को
  4. के सेट शरीर DoSomething इसी तरह के फैशन में System.Linq.Expressions

हमने हाल ही में खोज की Microsoft.CodeAnalysis.CSharp.SyntaxFactory, और यह आशाजनक प्रतीत होता था। हालांकि, जाहिर है हमें खुद को ट्रिविया जोड़ना है।

SyntaxFactory.CompilationUnit() के साथ एक पेड़ बनाने के बाद और कुछ सदस्यों को आगे और आगे जोड़ने के बाद, ToFullString() का आउटपुट केवल टेक्स्ट का एक गुच्छा है, जो न तो पठनीय है, न ही संकलित (उदा।, लापता ब्रेसिज़)। क्या मॉडल से पाठ उत्पन्न करते समय हमें कुछ याद आती है?

संपादित करें:

कार्यस्थानों उपयोग करते समय, आप सेट कर सकते हैं विकल्प खाली स्थान के व्यवहार को प्रभावित:

public string Generate (CompilationNode rootNode) 
{ 
    var cw = new CustomWorkspace(); 
    cw.Options.WithChangedOption (CSharpFormattingOptions.IndentBraces, true); 
    var formattedCode = Formatter.Format (CreateFile(rootNode), cw); 
    return formattedCode.ToFullString(); 
} 

यह पहले से ही बेहतर परिणाम अर्जित करता है। क्या कोई इसे एक अच्छे समाधान के रूप में पुष्टि कर सकता है या यह एक हैक है?

एक समस्या बनी हुई है। हम वर्तमान में SF.AccessorDeclaration का उपयोग कर एक ऑटो-प्रॉपर्टी जेनरेट करना चाहते हैं, लेकिन पूर्ण स्ट्रिंग में कनवर्ट करते समय अर्धविराम को याद करते हैं।

+0

आपका लक्ष्य कोड को निकालना है, है ना? संकलित नहीं है? – i3arnon

+0

हां, लेकिन स्पष्ट रूप से ट्रिविया निर्दिष्ट किए बिना। मेरे पास रीशेर्पर एसडीके का उपयोग करके कुछ अनुभव भी है, जो मूल रूप से एप्लिकेशन का एक ही क्षेत्र है। वे * कारखानों में होते हैं जो सामान्य ज्ञान के लिए अनजान होते हैं, और यह सभी जेनरेट किए गए कोड को साफ और संकलित करता है। मैंने कोडडॉम का उपयोग करने के लिए सुझाव देने वाले अन्य उपयोगकर्ताओं की कुछ टिप्पणियां पार कर लीं, और रोस्लिन इस के लिए उपयुक्त नहीं है, लेकिन यह अब तक का सबसे बड़ा असफल प्रतीत होता है :) – Matthias

+0

खैर ... रोज़लीन, एक कंपाइलर होने के नाते, कोड का उपभोग करने के लिए है, इसे उत्पन्न नहीं करते हैं। – i3arnon

उत्तर

10

आप मूल रूप से ब्लॉक परिभाषाओं को जोड़ने के लिए है, तो रोसलिन आप के लिए सामान्य ज्ञान जब तक आप फ़ॉर्मेटर का उपयोग करें (के रूप में आपके द्वारा लिखी गई)

यहाँ एक सरल वर्ग कि बिना सही ढंग से उत्पन्न होता है के लिए एक उदाहरण है संभालती है अपने आप को किसी भी सामान्य ज्ञान

var consoleWriteLine = Syntax.MemberAccessExpression(
     SyntaxKind.SimpleMemberAccessExpression, 
     Syntax.IdentifierName("Console"), 
     name: Syntax.IdentifierName("WriteLine")); 

    var arguments = Syntax.ArgumentList (
     Syntax.SeparatedList (
      new[] 
      { 
       Syntax.Argument (
        Syntax.LiteralExpression (
         SyntaxKind.StringLiteralExpression, 
         Syntax.Literal (@"""Goodbye everyone!""", "Goodbye everyone!"))) 
      })); 

    var consoleWriteLineStatement = Syntax.ExpressionStatement (Syntax.InvocationExpression (consoleWriteLine, arguments)); 

    var voidType = Syntax.ParseTypeName ("void"); 
    var method = Syntax.MethodDeclaration (voidType, "Method").WithBody (Syntax.Block(consoleWriteLineStatement)); 

    var intType = Syntax.ParseTypeName ("int"); 
    var getterBody = Syntax.ReturnStatement (Syntax.DefaultExpression (intType)); 
    var getter = Syntax.AccessorDeclaration (SyntaxKind.GetAccessorDeclaration, Syntax.Block (getterBody)); 
    var property = Syntax.PropertyDeclaration (intType, "Property").WithAccessorList (Syntax.AccessorList (Syntax.SingletonList (getter))); 

    var @class = Syntax.ClassDeclaration ("MyClass").WithMembers (Syntax.List (new MemberDeclarationSyntax[] { method, property })); 

    var cw = new CustomWorkspace(); 
    cw.Options.WithChangedOption (CSharpFormattingOptions.IndentBraces, true); 
    var formattedCode = Formatter.Format (@class, cw); 

    Console.WriteLine (formattedCode.ToFullString()); 

नोट निर्दिष्ट किए: सिंटैक्स = Microsoft.CodeAnalysis.CSharp.SyntaxFactory

यह निम्न सीएल उत्पन्न करता है गधा definiton:

class MyClass 
{ 
    void Method() 
    { 
     Console.WriteLine("Goodbye everyone!"); 
    } 

    int Property 
    { 
     get 
     { 
      return default(int); 
     } 
    } 
} 

ठीक लगता है।

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