4

私はこれについて調査しましたが、確かなものを見つけることができず、誰かが私を正しい方向に向けることができるかどうかを見たいと思っていました. 言語ごとに条件付き文字列を設定せずに、Codedom が異なる言語間の文字列と連結を処理できるかどうかを確認しようとしています。

たとえば、C# と VB.NET の両方で Codedom を使用して、以下に示すように正確に次のコードを生成する必要があります。

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 + """);")

CodeMethodInvokeExpressionforerrorMsg.ReplaceSystem.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 に答える
0

このクラスは、Alison が使用したようCodeTypeReferenceに ( http://msdn.microsoft.com/en-us/library/system.codedom.codetypereference.aspx ) 役立つはずです。

于 2010-08-18T13:04:40.470 に答える