Tengo una situación en la que necesito generar una clase con una const de cadena grande. El código fuera de mi control hace que mi árbol CodeDom generado se emita a la fuente C# y luego se compile como parte de un ensamblaje más grande.Solución temporal para C# CodeDom que causa el desbordamiento de pila (CS1647) en csc.exe?
Por desgracia, me he encontrado con una situación en la que si la longitud de esta cadena es superior a 335440 caracteres en Win2K8 x64 (926240 en Win2K3 x 86), las salidas compilador de C# con un error fatal:
fatal error CS1647: An expression is too long or complex to compile near 'int'
MSDN dice que CS1647 es "un desbordamiento de pila en el compilador" (¡sin juego de palabras!). Mirando más de cerca, he determinado que el CodeDom "muy bien" envuelve mi const de cadena a 80 caracteres. Esto hace que el compilador concatene más de 4193 fragmentos de cadena que aparentemente es la profundidad de la pila del compilador de C# en x64 NetFx. CSC.exe debe evaluar internamente recursivamente esta expresión para "rehidratar" mi cadena única.
Mi pregunta inicial es la siguiente: "¿alguien sabe de un trabajo en torno a cambiar la forma en que el generador de código emite cadenas?" No puedo controlar el hecho de que el sistema externo utiliza fuente C# como un producto intermedio y quiero esta ser una constante (en lugar de una concatenación de cadenas en tiempo de ejecución).
Alternativamente, cómo puedo formular esta expresión tal que después de un cierto número de caracteres, lo sigo siendo capaz de crear una constante, sino que está compuesto de múltiples grandes trozos?
repro completo está aquí:
// this string breaks CSC: 335440 is Win2K8 x64 max, 926240 is Win2K3 x86 max
string HugeString = new String('X', 926300);
CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
CodeCompileUnit code = new CodeCompileUnit();
// namespace Foo {}
CodeNamespace ns = new CodeNamespace("Foo");
code.Namespaces.Add(ns);
// public class Bar {}
CodeTypeDeclaration type = new CodeTypeDeclaration();
type.IsClass = true;
type.Name = "Bar";
type.Attributes = MemberAttributes.Public;
ns.Types.Add(type);
// public const string HugeString = "XXXX...";
CodeMemberField field = new CodeMemberField();
field.Name = "HugeString";
field.Type = new CodeTypeReference(typeof(String));
field.Attributes = MemberAttributes.Public|MemberAttributes.Const;
field.InitExpression = new CodePrimitiveExpression(HugeString);
type.Members.Add(field);
// generate class file
using (TextWriter writer = File.CreateText("FooBar.cs"))
{
provider.GenerateCodeFromCompileUnit(code, writer, new CodeGeneratorOptions());
}
// compile class file
CompilerResults results = provider.CompileAssemblyFromFile(new CompilerParameters(), "FooBar.cs");
// output reults
foreach (string msg in results.Output)
{
Console.WriteLine(msg);
}
// output errors
foreach (CompilerError error in results.Errors)
{
Console.WriteLine(error);
}
La versión csc.exe este se ejecuta bajo parece ser 2.0, a pesar de la orientación .NET 3.5. – mckamey