【问题标题】:Expanding a message template扩展消息模板
【发布时间】:2010-09-19 10:47:28
【问题描述】:

我有一组用于我的应用程序发送的电子邮件的模板。模板中嵌入了与我的业务对象的属性相对应的代码。

有没有比调用更优雅的方式

string.Replace("{!MyProperty!}", item.MyProperty.ToString()) 

无数次?也许是 XMLTransform、正则表达式或其他一些魔法?我正在使用 C# 3.5。

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    首先,当我这样做时,我使用 StringBuilder.Replace(),因为我发现它的性能更适合使用 3 个或更多替换。

    当然还有其他方法,但我发现通常不值得尝试其他项目。

    我猜你也许可以使用反射来自动替换,这可能是唯一“更好”的方法。

    【讨论】:

      【解决方案2】:
      public static string Translate(string pattern, object context)
      {
          return Regex.Replace(pattern, @"\{!(\w+)!}", match => {
              string tag = match.Groups[1].Value;
              if (context != null)
              {
                  PropertyInfo prop = context.GetType().GetProperty(tag);
                  if (prop != null)
                  {
                      object value = prop.GetValue(context);
                      if (value != null)
                      {
                          return value.ToString();
                      }
                  }
              }
              return "";
          });
      }
      
      Translate("Hello {!User!}. Welcome to {!GroupName!}!", new {
          User = "John",
          GroupName = "The Community"
      }); // -> "Hello John. Welcome to The Community!"
      

      https://ideone.com/D9J31c

      【讨论】:

      • 我添加了这个,以及其他解决方案。它删除了不匹配的字段,同时使用其他解决方案有效地填写可用字段。
      【解决方案3】:

      有一个内置的 WebControl,System.Web.UI.WebControls.MailDefinition,它执行string replacements(除其他外)。可惜他们将它与 app.config 中的 Smtp 设置和 Web 控件紧密耦合,然后将其密封以防止继承者使用。

      但是,它确实可以处理邮件模板引擎中最可能需要的一些内容——来自文件的正文、html 电子邮件、嵌入对象等。Reflector 显示实际替换是通过 foreach 循环和正则表达式处理的.Replace - 这对我来说也是一个合理的选择。

      快速浏览一下就会发现,如果您可以使用 app.config 中的发件人地址(您可以在之后在返回的 MailMessage 上更改它),那么您只需要嵌入资源的所有者控件或 BodyFileName。

      如果您使用的是 ASP.NET 或者可以忍受这些限制 - 我会选择 MailDefinition。否则,只需对字典和 Regex.Replace 进行 foreach。由于身体的重复分配,它有点占用内存 - 但它们的寿命很短,应该不会造成太大问题。

      var replacements = new Dictionary<string, object>() {
          { "Property1", obj.Property1 },
          { "Property2", obj.Property2 },
          { "Property3", obj.Property3 },
          { "Property4", obj.Property4 },
      }
      
      foreach (KeyValuePair<string, object> kvp in replacement) {
          body = Regex.Replace(body, kvp.Key, kvp.Value.ToString());
      }
      

      如果你真的有很多属性,那么先用 Regex.Match 读取你的正文,然后再反射到属性。

      【讨论】:

        【解决方案4】:

        您可以使用正则表达式来执行此操作,但您的正则表达式替换也因每个属性而异。我会坚持使用string.Replace

        使用反射检索属性并循环替换:

        foreach (string property in properties)
        {
          string.Replace("{!"+property+"!}",ReflectionHelper.GetStringValue(item,property));
        }
        

        只需实现您的ReflectionHelper.GetStringValue 方法并使用反射来检索您的项目对象类型的所有属性。

        【讨论】:

          【解决方案5】:

          在查看了之前包含的示例之后,我想我应该看看真正的代码。 @mark-brackett 你比你知道的更接近。

          //The guts of MailDefinition.CreateMailMessage
          //from https://github.com/Microsoft/referencesource/blob/master/System.Web/UI/WebControls/MailDefinition.cs
          
          if (replacements != null && !String.IsNullOrEmpty(body)) {
                              foreach (object key in replacements.Keys) {
                                  string fromString = key as string;
          string toString = replacements[key] as string;
          
                                  if ((fromString == null) || (toString == null)) {
                                      throw new ArgumentException(SR.GetString(SR.MailDefinition_InvalidReplacements));
                                  }
                                  // DevDiv 151177
                                  // According to http://msdn2.microsoft.com/en-us/library/ewy2t5e0.aspx, some special 
                                  // constructs (starting with "$") are recognized in the replacement patterns. References of
                                  // these constructs will be replaced with predefined strings in the final output. To use the 
                                  // character "$" as is in the replacement patterns, we need to replace all references of single "$"
                                  // with "$$", because "$$" in replacement patterns are replaced with a single "$" in the 
                                  // final output. 
                                  toString = toString.Replace("$", "$$");
                                  body = Regex.Replace(body, fromString, toString, RegexOptions.IgnoreCase);
                              }
                          }
          

          【讨论】:

            猜你喜欢
            • 2022-09-24
            • 1970-01-01
            • 1970-01-01
            • 2015-11-24
            • 2010-11-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多