代码之家  ›  专栏  ›  技术社区  ›  Todd Main

codedom和字符串处理

  •  4
  • Todd Main  · 技术社区  · 14 年前

    我已经研究过这个问题,但找不到任何可靠的证据,我想看看是否有人能给我指明正确的方向。我正在尝试查看codedom是否可以处理字符串和不同语言之间的重叠,而不需要为每种语言设置条件字符串。

    例如,我需要生成以下内容 如下图所示 通过codedom在c和vb.net中:

    C.*

    errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
    System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");  
    

    VB.NET

    errorMsg = errorMsg.Replace(""""c, "'"c).Replace(ChrW(13) & ChrW(10), "\n")
    System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(""Unhandled Error in Silverlight Application " + errorMsg + """);")
    

    这个 CodeMethodInvokeExpression 对于 errorMsg.Replace System.Windows.Browser.HtmlPage.Window.Eval 很简单,我无法确定codedom是否可以自动处理它们内部的字符串。

    4 回复  |  直到 14 年前
        1
  •  3
  •   NakedBrunch    14 年前

    不幸的是,当代码原语组合在一起时,并不总是产生期望的结果,因为提供程序将具有一定的自由度来解释意图。解决这个问题的方法是使用 CodeSnippetExpression .

    下面是代码(vb.net&c),用于生成问题中列出的eval语句。请随意使用最适合您的工具:

    VB.NET版本

    Imports System.CodeDom
    Imports System.CodeDom.Compiler
    Imports System.Reflection
    Imports System.Text
    Imports System.IO
    Imports Microsoft.CSharp
    
    Public Class PrintEvalStatement
        Public provider As CodeDomProvider
    
        Sub New()
            Dim left As New CodePrimitiveExpression("throw new Error(""Unhandled Error in Silverlight Application ")
            Dim middle As New CodeVariableReferenceExpression("errorMsg")
            Dim right As New CodePrimitiveExpression(""");")
    
            Dim targetObject = New CodeTypeReferenceExpression("System.Windows.Browser.HtmlPage.Window")
            Dim methodName = "Eval"
    
            provider = New VBCodeProvider()
            Dim vbStatement As String = ConcatStatement(left, middle, right, targetObject, methodName)
    
            provider = New CSharpCodeProvider()
            Dim csStatement As String = ConcatStatement(left, middle, right, targetObject, methodName)
    
            Console.WriteLine(vbStatement)
            Console.WriteLine(csStatement)
            Console.ReadLine()
        End Sub
    
        Private Function ConcatStatement(ByVal left As CodePrimitiveExpression,
                                         ByVal middle As CodeVariableReferenceExpression,
                                         ByVal right As CodePrimitiveExpression,
                                         ByVal targetObject As CodeTypeReferenceExpression,
                                         ByVal methodName As String) As String
            Dim evalMessage As New CodeExpression
            evalMessage = ConcatString(left, middle, right)
    
            Dim eval As New CodeMethodInvokeExpression(targetObject, methodName, evalMessage)
            Dim evalStatement As New CodeExpressionStatement(eval)
            Dim sw As StringWriter = New StringWriter()
    
            Using tx As TextWriter = New StringWriter()
                provider.GenerateCodeFromStatement(evalStatement, tx, New CodeGeneratorOptions())
                Return tx.ToString()
            End Using
        End Function
        Private Function ConcatString(ByVal left As CodeExpression,
                                      ByVal middle As CodeExpression,
                                      ByVal right As CodeExpression) As CodeExpression
            Return New CodeSnippetExpression(CodeToString(left) + " + " + CodeToString(middle) + " + " + CodeToString(right))
        End Function
        Private Function CodeToString(ByVal expr As CodeExpression) As String
            Using tx As TextWriter = New StringWriter()
                provider.GenerateCodeFromExpression(expr, tx, New CodeGeneratorOptions())
                Return tx.ToString()
            End Using
        End Function
    
    
    End Class
    

    C版本

    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.Reflection;
    using System.Text;
    using System.IO;
    using Microsoft.CSharp;
    using Microsoft.VisualBasic;
    
    namespace CodeDom
    {
        class Program
        {       
            static CodeDomProvider provider;
    
            static void Main(string[] args)
            {
                Program shell = new Program();
                provider = new VBCodeProvider();
                CodePrimitiveExpression left = new CodePrimitiveExpression("throw new Error(\"Unhandled Error in Silverlight Application\")");
                CodeVariableReferenceExpression middle = new CodeVariableReferenceExpression("errorMsg");
                CodePrimitiveExpression right = new CodePrimitiveExpression("\");");
    
                CodeTypeReferenceExpression targetObject = new CodeTypeReferenceExpression("System.Windows.Browser.HtmlPage.Window");
                string methodName = "Eval";
    
                string vbStatement =  shell.ConcatStatement(left, middle, right, targetObject, methodName);
    
                provider = new CSharpCodeProvider();
    
                string csStatement = shell.ConcatStatement(left, middle, right, targetObject, methodName);
    
                Console.WriteLine(vbStatement);
                Console.WriteLine(csStatement);
                Console.ReadLine();
    
            }
    
            public string ConcatStatement(CodePrimitiveExpression left, CodeVariableReferenceExpression middle, CodePrimitiveExpression right, CodeTypeReferenceExpression targetObject, string methodName)
            {
                CodeExpression evalMessage = new CodeExpression();
                evalMessage = ConcatString(left, middle, right);
    
                CodeMethodInvokeExpression eval = new CodeMethodInvokeExpression(targetObject, methodName, evalMessage);
                CodeExpressionStatement evalStatement = new CodeExpressionStatement(eval);
                using (TextWriter tx = new StringWriter())
                {
                    provider.GenerateCodeFromStatement(evalStatement, tx, new CodeGeneratorOptions());
                    return tx.ToString();
                }
            }
    
            private CodeExpression ConcatString(CodeExpression left, CodeExpression middle, CodeExpression right) {
                return new CodeSnippetExpression(CodeToString(left) + " + " + CodeToString(middle) + " + " + CodeToString(right));
            }
    
            private string CodeToString(CodeExpression expr) {
                using (TextWriter tx = new StringWriter()) {
                    provider.GenerateCodeFromExpression(expr,tx, new CodeGeneratorOptions());
                    return tx.ToString();
                }
            }
        }
    }
    
        2
  •  1
  •   Kirk Woll    14 年前

    更新 : 我刚试过以下代码:

    VBCodeProvider vbProvider = new VBCodeProvider();
    CSharpCodeProvider csProvider = new CSharpCodeProvider();
    
    var errorMessagePart1 = new CodePrimitiveExpression("Unhandled Error in Silverlight Application \"");
    var errorMessagePart2 = new CodeVariableReferenceExpression("errorMsg");
    var errorMessagePart3 = new CodePrimitiveExpression("\"");
    var errorMessage = new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(errorMessagePart1, CodeBinaryOperatorType.Add, errorMessagePart2), CodeBinaryOperatorType.Add, errorMessagePart3);
    var expression = new CodeThrowExceptionStatement(new CodeObjectCreateExpression("Error", errorMessage));
    
    StringWriter writer = new StringWriter();
    vbProvider.GenerateCodeFromStatement(expression, writer, new CodeGeneratorOptions());
    string vb = writer.ToString();
    writer = new StringWriter();
    csProvider.GenerateCodeFromStatement(expression, writer, new CodeGeneratorOptions());
    string cs = writer.ToString();
    
    Console.WriteLine(vb);
    Console.WriteLine(cs);
    

    它打印出来:

    Throw New [Error]((("Unhandled Error in Silverlight Application """ + errorMsg) _ 
        + """"))
    
    throw new Error((("Unhandled Error in Silverlight Application \"" + errorMsg)
        + "\""));
    

    在我看来,它就像是一个VB版本和一个C版本。对于虚假的括号,你不能做太多的事情,但不应该造成任何伤害。

        3
  •  1
  •   Kris    14 年前

    您可以调用string.concat,而不是使用+运算符,除非您需要生成如图所示的代码。

    CodePrimitiveExpression throwstring = new CodePrimitiveExpression("throw new Error(\"Unhandled Error in Silverlight Application ");
    CodeVariableReferenceExpression errorMsg = new CodeVariableReferenceExpression("errorMsg");
    CodePrimitiveExpression end = new CodePrimitiveExpression("\");");
    
    CodeTypeReferenceExpression targetObject = new CodeTypeReferenceExpression("System.Windows.Browser.HtmlPage.Window");
    CodeTypeReferenceExpression str = new CodeTypeReferenceExpression(typeof(string));
    CodeMethodInvokeExpression concat = new CodeMethodInvokeExpression(str,"Concat",throwstring,errorMsg,end);
    CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(targetObject, "Eval"), concat);
    

    C输出:

    System.Windows.Browser.HtmlPage.Window.Eval(string.Concat("throw new Error(\"Unhandled Error in Silverlight Application ", errorMsg, "\");"))
    

    VB:

    System.Windows.Browser.HtmlPage.Window.Eval(String.Concat("throw new Error(""Unhandled Error in Silverlight Application ", errorMsg, """);"))
    
        4
  •  0
  •   Chris Laplante    14 年前

    班级 CodeTypeReference 应该帮你的( http://msdn.microsoft.com/en-us/library/system.codedom.codetypereference.aspx ,正如艾莉森所用。