【问题标题】:C# GenerateCodeFromCompileUnit is Generating Code with Special Characters [Microsoft.CSharp.CSharpCodeProvider]C# GenerateCodeFromCompileUnit 正在生成带有特殊字符的代码 [Microsoft.CSharp.CSharpCodeProvider]
【发布时间】:2022-01-18 16:11:22
【问题描述】:

我正在使用GenerateCodeFromCompileUnitIndentedTextWriterC# 源文件生成代码。这样做我可以生成一个.cs 文件。但是我看到在每个声明的变量和函数返回类型之前插入了一个特殊字符 @。这是我的代码。

我正在使用Class 来保存要插入的函数详细信息。

Dim provider As Microsoft.CSharp.CSharpCodeProvider
Dim options = New System.CodeDom.Compiler.CompilerParameters
options.ReferencedAssemblies.Add("System.dll")
options.GenerateExecutable = False
options.GenerateInMemory = True
options.IncludeDebugInformation = True
options.OutputAssembly = "FunctionEvaluated.dll"

Dim compileUnit As System.CodeDom.CodeCompileUnit
compileUnit = New CodeDom.CodeCompileUnit
Dim codeNamespace = New CodeDom.CodeNamespace("NewNamespace")

compileUnit.Namespaces.Add(codeNamespace)

Dim classForCompile = New CodeDom.CodeTypeDeclaration("NewAction")
codeNamespace.Types.Add(classForCompile)

Dim functionToEvaluate = New CodeDom.CodeMemberMethod()

Dim returnType As CodeDom.CodeTypeReference

If functionClass.FunctionNameAndType.Select(Function(fn) fn.Value)(0).ToString() = "void" Then
    returnType = New CodeDom.CodeTypeReference("void")
Else

    returnType = New CodeDom.CodeTypeReference(functionClass.FunctionNameAndType.Select(Function(fn) fn.Value)(0).ToString())
End If

Dim parameterExpressionCollection = New CodeDom.CodeParameterDeclarationExpressionCollection()

For Each ip In functionClass.FunctionNameIP


    For Each fnIP In ip.Value
        Dim parameterExpression As CodeDom.CodeParameterDeclarationExpression
        parameterExpression = New CodeDom.CodeParameterDeclarationExpression(fnIP.Value.ToString(), fnIP.Key.ToString())

        parameterExpressionCollection.Add(parameterExpression)
    Next
Next

functionToEvaluate.Name = functionClass.FunctionNameAndType.Select(Function(fn) fn.Key)(0).ToString()
functionToEvaluate.ReturnType = returnType
functionToEvaluate.Parameters.AddRange(parameterExpressionCollection)


classForCompile.Members.Add(functionToEvaluate)

provider = New Microsoft.CSharp.CSharpCodeProvider
Dim sourceFile As String
sourceFile = "FunctionEvaluated.cs"
Dim tw As IndentedTextWriter = New IndentedTextWriter(New StreamWriter(sourceFile, False), vbTab)
provider.GenerateCodeFromCompileUnit(compileUnit, tw, New CodeGeneratorOptions())
tw.Close()

输出

//------------------------------------------------------------------------------
// <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 NewNamespace {
    
    
    public class NewAction {
        
        private @int functionAdd(@int b, @int a) {
        }
    }
}

【问题讨论】:

  • 顺便说一句,您的代码真的可以使用大写的New,而不是new吗?
  • 顺便说一下,上面我生成的代码是用VB.Net编写的,所以New是大写的。
  • 抱歉,我什至没有注意到这一点。必须检查 Type.GetType(String) 是否可用。基于docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/… 我想是的。您可能需要使用“Integer”作为字符串而不是“int”。
  • 但是 functionClass.FunctionNameAndType.Select(Function(fn) fn.Value)(0).ToString()) 具有“int”。如果我将它传递给 Type.GetType("int") 它会返回“Nothing”。
  • “Integer”在 Visual Basic 中与 c# 中的“int”类型相同,因此该函数在从 Visual Basic 调用时需要“Integer”,并在代码中输出“int”。或者您可以摆脱对 Type.GetType() 的调用,但在数据中使用“Int32”而不是“int”。 “Int32”不是关键字,因此不会与前面的@一起输出。

标签: c# streamwriter codedom system-codedom-compiler


【解决方案1】:

我相信你的问题出在线条上

New CodeDom.CodeTypeReference(functionClass.FunctionNameAndType.Select(Function(fn) fn.Value)(0).ToString())

parameterExpression = New CodeDom.CodeParameterDeclarationExpression(fnIP.Value.ToString(), fnIP.Key.ToString())

我怀疑使用字符串指定本机类型会导致 DOM 认为这是用户定义的类型“int”并用 @ 屏蔽它以防止使用本机 int。来自https://en.wikipedia.org/wiki/C_Sharp_syntax#Keywords

如果需要与保留关键字相同的标识符,则可以在其前面加上@字符以区分它

要确保输出使用像 int 这样的本机类型,您可以尝试使用

new CodeTypeReference(typeof(int))

换句话说,使用真正的Typepublic CodeTypeReference(Type type); 构造函数。

要从命名类型的字符串中获取真正的类型,可以使用Type.GetType(String) 函数。

所以试试这个:

New CodeDom.CodeTypeReference(Type.GetType(functionClass.FunctionNameAndType.Select(Function(fn) fn.Value)(0).ToString()))

parameterExpression = New CodeDom.CodeParameterDeclarationExpression(Type.GetType(fnIP.Value.ToString()), fnIP.Key.ToString())

【讨论】:

  • 谢谢克里斯托弗。为此,我附加了“System”关键字,然后尝试使用 Type.GetType("System" & fnIP.Value.ToString()), fnIP.Key.ToString()) 然后它起作用了。
猜你喜欢
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-03
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多