4

我对此进行了研究,但找不到任何可靠的东西,并想看看是否有人可以为我指明正确的方向。我正在尝试查看 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 + """);")

CodeMethodInvokeExpressionfor errorMsg.ReplaceandSystem.Windows.Browser.HtmlPage.Window.Eval很简单,就是它们里面的字符串我不知道 Codedom 能不能自动处理。

4

4 回答 4

3

不幸的是,代码原语在组合时并不总是产生预期的结果,因为提供者会采取某些自由来解释意图。解决这个问题的方法是使用CodeSnippetExpression

这是用于生成您在问题中列出的 Eval 语句的代码(VB.NET 和 C#)。随意使用最适合您的:

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();
            }
        }
    }
}
于 2010-08-17T21:46:17.447 回答
1

更新:我刚刚尝试了以下代码:

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# 版本。你不能对虚假括号做很多事情,但不应该造成任何伤害。

于 2010-08-15T16:43:29.857 回答
1

您可以调用 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, """);"))
于 2010-08-17T22:15:16.827 回答
0

正如艾莉森使用的那样,该课程CodeTypeReference应该可以帮助您 ( http://msdn.microsoft.com/en-us/library/system.codedom.codetypereference.aspx )。

于 2010-08-18T13:04:40.470 回答