我可以在运行时扩展包含C#文字表达式的字符串

如果我有一个包含ac#string文字表达式的字符串,我可以在运行时“展开”它

public void TestEvaluateString() { string Dummy = EvalString( @"Contains \r\n new line"); Debug.Assert(Dummy == "Contains \r\n new line"); } private string EvalString(string input) { return "Contains \r\n new line"; } 

就像我可以将C#字符串值转换为转义字符串文字 ,但反过来?

类似于Mikael的答案,但使用CSharpCodeProvider:

  public static string ParseString(string txt) { var provider = new Microsoft.CSharp.CSharpCodeProvider(); var prms = new System.CodeDom.Compiler.CompilerParameters(); prms.GenerateExecutable = false; prms.GenerateInMemory = true; var results = provider.CompileAssemblyFromSource(prms, @" namespace tmp { public class tmpClass { public static string GetValue() { return " + "\"" + txt + "\"" + @"; } } }"); System.Reflection.Assembly ass = results.CompiledAssembly; var method = ass.GetType("tmp.tmpClass").GetMethod("GetValue"); return method.Invoke(null, null) as string; } 

你可能最好使用通配符字典,只需在字符串中替换它们。

不确定这是否是最简单的方法,但通过引用Microsoft.JScript命名空间,您可以使用javascript eval函数重新解析它。

这是对底部代码的测试

 var evalToString = Evaluator.MyStr("test \\r\\n test"); 

这会将\ r变为回车符。

并实施

 public class Evaluator { public static object MyStr(string statement) { return _evaluatorType.InvokeMember( "MyStr", BindingFlags.InvokeMethod, null, _evaluator, new object[] { statement } ); } static Evaluator() { ICodeCompiler compiler; compiler = new JScriptCodeProvider().CreateCompiler(); CompilerParameters parameters; parameters = new CompilerParameters(); parameters.GenerateInMemory = true; CompilerResults results; results = compiler.CompileAssemblyFromSource(parameters, _jscriptSource); Assembly assembly = results.CompiledAssembly; _evaluatorType = assembly.GetType("Evaluator.Evaluator"); _evaluator = Activator.CreateInstance(_evaluatorType); } private static object _evaluator = null; private static Type _evaluatorType = null; private static readonly string _jscriptSource = @"package Evaluator { class Evaluator { public function MyStr(expr : String) : String { var x; eval(""x='""+expr+""';""); return x; } } }"; } 

如果您只是想在Microsoft站点上定义“简单”转义字符,则可以使用此例程并保存导入外部库:

 public static class StringExtensions { /* https://msdn.microsoft.com/en-us/library/aa691087(v=vs.71).aspx */ private readonly static SortedDictionary EscapeMap = new SortedDictionary { { '\'', '\'' }, { '"', '\"' }, { '\\', '\\' }, { '0', '\0' }, { 'a', '\a' }, { 'b', '\b' }, { 'f', '\f' }, { 'n', '\n' }, { 'r', '\r' }, { 't', '\t' }, { 'v', '\v' }, }; public static string UnescapeSimple(this string escaped) { if (escaped == null) return escaped; var sb = new StringBuilder(); bool inEscape = false; var s = 0; for (var i = 0; i < escaped.Length; i++) { if (!inEscape && escaped[i] == '\\') { inEscape = true; continue; } if (inEscape) { char mapChar; if (EscapeMap.TryGetValue(escaped[i], out mapChar)) { sb.Append(escaped.Substring(s, i - s - 1)); sb.Append(mapChar); s = i + 1; } inEscape = false; } } sb.Append(escaped.Substring(s)); return sb.ToString(); } } 

这是一个unit testing来certificate它:

  [TestMethod] public void UnescapeSimpleTest() { var noEscapes = @"This is a test".UnescapeSimple(); Assert.AreEqual("This is a test", noEscapes, nameof(noEscapes)); var singleEscape = @"\n".UnescapeSimple(); Assert.AreEqual("\n", singleEscape, nameof(singleEscape)); var allEscape = @"\'\""\\\0\a\b\f\n\r\t\v".UnescapeSimple(); Assert.AreEqual("\'\"\\\0\a\b\f\n\r\t\v", allEscape, nameof(allEscape)); var textInEscapes = @"\tthis\n\ris\\a\ntest".UnescapeSimple(); Assert.AreEqual("\tthis\n\ris\\a\ntest", textInEscapes, nameof(textInEscapes)); var backslashNoEscapes = @"\,\h\qtest".UnescapeSimple(); Assert.AreEqual(@"\,\h\qtest", backslashNoEscapes, nameof(backslashNoEscapes)); var emptyStr = "".UnescapeSimple(); Assert.AreEqual("", emptyStr, nameof(emptyStr)); // Prove Enviroment.NewLine is "\r\n" and not "\n\r" (Windows PC) var newLine = @"\r\n".UnescapeSimple(); Assert.AreEqual(Environment.NewLine, newLine, nameof(newLine)); // Double check prior test (Windows PC) var newLineWrong = @"\n\r".UnescapeSimple(); Assert.AreNotEqual(Environment.NewLine, newLineWrong, nameof(newLineWrong)); } 

随意调整EscapeMap或重命名函数UnescapeSimple(我知道这很尴尬)。

请注意,此解决方案不处理Unicode转义字符或hex或八进制,它只处理简单的单字符。

Regex.Unescape将是我的首选方法。