首页 > 解决方案 > 静态上下文中的 C# 字符串插值

问题描述

我目前正在尝试将类生成为具有一些属性的字符串,我必须在编译代码之前设置这些属性。

让我们看看我的代码,我使用的是静态字符串:

    public class NewHumanSource
    {
            static readonly string template =
                "internal class {ClassName} : IHuman " + 
                "{ " +
                     // bunch of private fields here;
                     "private int age; " + Environment.NewLine +

                     "public int Age" + Environment.NewLine +
                     "{" + Environment.NewLine +
                          "get =>" + $"{int.Parse("{Age}")}" + ";" + Environment.NewLine +
                          "set" + Environment.NewLine +
                          "{" + Environment.NewLine +
                               "age= value;" + Environment.NewLine +
                               "OnPropertyChanged(nameof(age));" +Environment.NewLine +      
                          "}" + Environment.NewLine +
                     "}" + Environment.NewLine + Environment.NewLine +

                      // Other properties and members
                ";"

用于为源代码模板设置值的静态成员:

 public static string GetSourceCode(IHuman newHuman, string className)
 {
     code = code.Replace("{ClassName}", className.ToLowerInvariant().Replace(" ", ""));
     code = code.Replace("{Age}", newHuman.Age.ToString()); //Age is an integer.
     //...
 }

然后从外部类调用:

 var code = NewHumanSource.GetSourceCode(newHuman, className);

在该行引发异常。静态方法甚至不会加载:

System.TypeInitializationException: 'The type initializer for 'DynamicCompilerTest.Classes.DynamicCompiler.NewHumanSource' threw an exception.'

InnerException  {"Input string was not in a correct format."}   System.Exception {System.FormatException}

如果所有属性都是字符串,它会工作得很好,但是这个字符串插值会引发异常:

 "get =>" + $"{int.Parse("{Age}")}" + ";" +

知道我应该如何处理非字符串类型吗?我需要处理像 DateTime 这样的内置类型。或者有没有更优雅的方式来创建一个具有属性值的文本类?我可能会得到格式化。

非常感谢您的帮助/提示!

标签: c#stringdynamiccompilationinterpolation

解决方案


这不会以这种方式工作。int.Parse("{Age}")将在类型初始化期间进行评估,因此它不能使用Age. 根据您的代码,我相信您只需将其替换为return age.

您还可以从使用多行字符串文字中受益:

static readonly string template =
    @"internal class {ClassName} : IHuman 
      {
          // bunch of private fields here
          private int age = {Age};

          public int Age
          {
              get { return age; }
              set
              {
                  age = value;
                  OnPropertyChanged(nameof(Age));
              }
          }

          // Other properties and members
      }";

推荐阅读