如何通过CodeDOM或Linq Expression动态生成条件块?

时间:2010-08-02 14:17:45

标签: codedom

if ((x == 1 && y == "test") || str.Contains("test"))
  ...

如何用CodeDOM或LinqExpression动态地用C#在if块中生成条件?

2 个答案:

答案 0 :(得分:4)

要允许您使用纯CodeDom创建表达式,您可以使用CodeBinaryOperationExpression中的CodeConditionStatement

条件如下:

CodeExpression condition = new CodeBinaryOperatorExpression(
    new CodeBinaryOperatorExpression(
        new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("x"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(1)),
        CodeBinaryOperatorType.BooleanAnd,
        new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("y"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression("test"))),
    CodeBinaryOperatorType.BooleanOr,
    new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeVariableReferenceExpression("str"), "Contains"), new CodePrimitiveExpression("test")));

那么你需要的只是真实的,可选的假的陈述:

CodeStatement[] trueStatements = { new CodeCommentStatement("Do this if true") };
CodeStatement[] falseStatements = { new CodeCommentStatement("Do this is false") };

然后将所有内容放在if语句中:

CodeConditionStatement ifStatement = new CodeConditionStatement(condition, trueStatements, falseStatements);

使用执行评估的方法创建类的完整示例可能如下所示:

CodeCompileUnit compileUnit = new CodeCompileUnit();
CodeNamespace exampleNamespace = new CodeNamespace("StackOverflow");
CodeTypeDeclaration exampleClass = new CodeTypeDeclaration("GeneratedClass");

CodeMemberMethod method = new CodeMemberMethod();
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
method.Name = "EvaluateCondition";
method.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "x"));
method.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "y"));
method.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "str"));

CodeExpression condition = new CodeBinaryOperatorExpression(
    new CodeBinaryOperatorExpression(
        new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("x"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(1)),
        CodeBinaryOperatorType.BooleanAnd,
        new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("y"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression("test"))),
    CodeBinaryOperatorType.BooleanOr,
    new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeVariableReferenceExpression("str"), "Contains"), new CodePrimitiveExpression("test")));

CodeStatement[] trueStatements = { new CodeCommentStatement("Do this if true") };

CodeStatement[] falseStatements = { new CodeCommentStatement("Do this if false") };

CodeConditionStatement ifStatement = new CodeConditionStatement(condition, trueStatements, falseStatements);

method.Statements.Add(ifStatement);
exampleClass.Members.Add(method);
exampleNamespace.Types.Add(exampleClass);
compileUnit.Namespaces.Add(exampleNamespace);

使用此代码在C#中生成源输出...

string sourceCode;
using (var provider = CodeDomProvider.CreateProvider("csharp"))
using (var stream = new MemoryStream())
using (TextWriter writer = new StreamWriter(stream))
using (IndentedTextWriter indentedWriter = new IndentedTextWriter(writer, "    "))
{
    provider.GenerateCodeFromCompileUnit(compileUnit, indentedWriter, new CodeGeneratorOptions()
    {
        BracingStyle = "C"
    });

    indentedWriter.Flush();

    stream.Seek(0, SeekOrigin.Begin);
    using (TextReader reader = new StreamReader(stream))
    {
        sourceCode = reader.ReadToEnd();
    }
}

... sourceCode将包含:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace StackOverflow
{


    public class GeneratedClass
    {

        public void EvaluateCondition(int x, string y, string str)
        {
            if ((((x == 1) 
                        && (y == "test")) 
                        || str.Contains("test")))
            {
                // Do this if true
            }
            else
            {
                // Do this if false
            }
        }
    }
}

将提供商从csharp更改为vb以获取此信息:

'------------------------------------------------------------------------------
' <auto-generated>
'     This code was generated by a tool.
'     Runtime Version:4.0.30319.42000
'
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------

Option Strict Off
Option Explicit On


Namespace StackOverflow

    Public Class GeneratedClass

        Public Sub EvaluateCondition(ByVal x As Integer, ByVal y As String, ByVal str As String)
            If (((x = 1)  _
                        AndAlso (y = "test"))  _
                        OrElse str.Contains("test")) Then
                'Do this if true
            Else
                'Do this if false
            End If
        End Sub
    End Class
End Namespace

答案 1 :(得分:1)

要使用codedom创建动态上面的代码,您需要执行以下操作:

创建一个可添加到类中的方法:

CodeMemberMethod method = new CodeMemberMethod();

method.Name = "TestMethod";
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;

在括号内创建一个包含语句的If命令,例如{Value = 4;}

CodeConditionStatement codeIf = new CodeConditionStatement(new
CodeSnippetExpression("(x == 1 && y == \"test\")|| str.Contains(\"test\")"), new 
            CodeSnippetStatement("value = 4;"));

将If命令添加到上面创建的方法:

method.Statements.Add(codeIf);