C#中如何存储插值字符串模板?适配现有继承类场景
可行解决方案
方案一:自定义消息容器类(兼容现有代码,推荐)
这个方案通过创建同时支持string和FormattableString的容器类,修改基类的Message字段类型为该容器,实现无缝兼容所有现有赋值代码,同时捕获插值字符串模板。
步骤1:创建MessageContainer容器类
public class MessageContainer { // 存储最终渲染后的字符串 public string StringValue { get; } // 存储插值模板(仅当赋值为插值字符串时不为null) public FormattableString Template { get; } private MessageContainer(string value) { StringValue = value; Template = null; } private MessageContainer(FormattableString template) { StringValue = template.ToString(); Template = template; } // 隐式转换:string自动转为MessageContainer public static implicit operator MessageContainer(string value) { return new MessageContainer(value); } // 隐式转换:插值字符串(FormattableString)自动转为MessageContainer public static implicit operator MessageContainer(FormattableString template) { return new MessageContainer(template); } // 隐式转换:MessageContainer自动转为string,兼容原有需要string的场景 public static implicit operator string(MessageContainer container) { return container.StringValue; } }
步骤2:修改BaseMessage的Message字段类型
将基类中的string Message字段改为MessageContainer类型的属性:
public class BaseMessage { public MessageContainer Message { get; set; } // ...其他原有代码 }
步骤3:ProcessMessage无需修改
子类继承基类后,原有实例化代码完全不需要改动:
public class ProcessMessage : BaseMessage { // ...原有代码 }
使用效果
三种赋值方式均正常工作,且能捕获插值模板:
// 插值字符串:Template会保存模板和参数 var msg1 = new ProcessMessage { Message = $"User {userId} logged in" }; // 普通字符串:Template为null var msg2 = new ProcessMessage { Message = "System started" }; // 字符串变量:Template为null var msg3 = new ProcessMessage { Message = customMessage }; // 获取模板示例 if (msg1.Message.Template != null) { string formatTemplate = msg1.Message.Template.Format; // 输出 "User {0} logged in" object[] templateArgs = msg1.Message.Template.GetArguments(); // 输出 [userId] // 在这里实现模板存储逻辑 }
方案二:编译时代码批量修复(无法修改基类时使用)
如果无法修改BaseMessage的Message字段类型,可以用Roslyn编写代码分析器,批量将插值字符串的赋值替换为专用方法调用,从而捕获FormattableString:
步骤1:给ProcessMessage添加专用方法
public class ProcessMessage : BaseMessage { public FormattableString MessageTemplate { get; private set; } public void SetMessage(FormattableString template) { MessageTemplate = template; Message = template.ToString(); } }
步骤2:用Roslyn工具批量修改代码
通过代码分析器自动将所有:
var ret = new ProcessMessage() { Message = $"Some info {param}" };
替换为:
var ret = new ProcessMessage(); ret.SetMessage($"Some info {param}");
普通字符串和变量赋值的代码保持不变。
这种方式无需修改运行时逻辑,仅通过编译时工具完成批量代码调整,适合无法修改基类的场景。
内容的提问来源于stack exchange,提问作者bleat interteiment
相关产品推荐
相关产品推荐

