扩展消息模板

时间:2008-10-27 18:23:01

标签: c# regex

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

是否有一种比调用

更优雅的方式
string.Replace("{!MyProperty!}", item.MyProperty.ToString()) 
几百万次?也许是XMLTransform,正则表达式或其他一些魔术?我正在使用C#3.5。

5 个答案:

答案 0 :(得分:3)

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

当然还有其他方法可以做到这一点,但我发现尝试其他项目通常不值得付出额外的努力。

您可以使用反射我想自动更换,这可能是唯一“更好”的方式。

答案 1 :(得分: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

答案 2 :(得分:1)

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

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

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

只需实施ReflectionHelper.GetStringValue方法并使用反射来检索商品对象类型的所有属性。

答案 3 :(得分:1)

内置WebControl,System.Web.UI.WebControls.MailDefinition执行string replacements(以及其他内容)。遗憾的是,他们将它紧密地耦合到app.config中的Smtp设置和一个Web控件,然后将其密封以保护继承者。

但是,它确实处理了你在邮件模板引擎中最想要的一些东西 - 来自文件,html电子邮件,嵌入对象等的正文文本.Reflector显示实际的替换是用foreach循环和Regex处理的.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 :(得分:0)

看完前面包括的示例后,我想我会看一下真正的代码。 @ mark-brackett你比你知道的要近。

declare @a GEOMETRY = Geometry::STGeomFromText('LINESTRING (-83 24, -80.4907132243685 24.788632986627039)', 4326)
declare @b GEOMETRY = Geometry::STGeomFromText('LINESTRING (-74.7 21.8, -75.7 22.1, -77.8 22.6, -79.4 23.3, -80.4 24.5, -81.5 28, -84 33, -87 36)', 4326)


DECLARE @intersectionPoint geometry = @a.STIntersection(@b) -- POINT (-80.49071322436852 24.788632986627078)

IF @intersectionPoint IS NULL
    THROW 50000, '@intersectionPoint not found', 1


-- Expect 1, Result 0
SELECT @b.STIntersects(@intersectionPoint)