列表中的电子邮件生成器迭代

时间:2019-06-20 10:12:20

标签: c# list iteration ienumerable

我编写了一个函数,该函数生成HTML电子邮件并用数据库中的信息填充它。

我一直在尝试遍历列表,但似乎无法使该函数具有通用性,并且无法遍历Items列表。

这是电子邮件生成器功能。它相当通用,因此可以在各种电子邮件模板中使用。

    public interface IMailObject
    {
        string Subject { get; }
    }

    public interface IEmailGenerator
    {
        MailMessage generateEmail(IMailObject mailObject, string htmlTemplate, string textTemplate);
    }

    public class EmailGenerator : IEmailGenerator, IRegisterInIoC
    {   
        private string mergeTemplate(string template, object obj)
        {
            Regex operationParser = new Regex(@"\$(?:(?<operation>[\w\-\,\.]+)\x20)(?<value>[\w\-\,\.]+)\$", RegexOptions.Compiled);
            Regex valueParser = new Regex(@"\$(?<value>[\w\-\,\.]+)\$", RegexOptions.Compiled);

            var operationMatches = operationParser.Matches(template).Cast<Match>().Reverse().ToList();
            foreach (var match in operationMatches)
            {
                string operation = match.Groups["operation"].Value;
                string value = match.Groups["value"].Value;
                var propertyInfo = obj.GetType().GetProperty(value);
                if (propertyInfo == null)
                    throw new TillitException(String.Format("Could not find '{0}' in object of type '{1}'.", value, obj));

                object dataValue = propertyInfo.GetValue(obj, null);

                if (operation == "endforeach")
                {
                    string foreachToken = "$foreach " + value + "$";
                    var startIndex = template.LastIndexOf(foreachToken, match.Index);
                    var templateBlock = template.Substring(startIndex + foreachToken.Length, match.Index - startIndex - foreachToken.Length);
                    var items = (IEnumerable) value;

                    string blockResult = "";

                    foreach (object item in items)
                    {
                        blockResult += mergeTemplate(templateBlock, item);
                    }

                    template = template.Remove(startIndex, match.Index - startIndex).Insert(startIndex, blockResult);
                }
            }

            var valueMatches = valueParser.Matches(template).Cast<Match>().Reverse().ToList();
            foreach (var match in valueMatches)
            {
                string value = match.Groups["value"].Value;
                var propertyInfo = obj.GetType().GetProperty(value);
                if (propertyInfo == null)
                    throw new Exception(String.Format("Could not find '{0}' in object of type '{1}'.", value, obj));

                object dataValue = propertyInfo.GetValue(obj, null);

                template = template.Remove(match.Index, match.Length).Insert(match.Index, dataValue.ToString());
            }

            return template;
        }

        public MailMessage generateEmail(IMailObject mailObject, string htmlTemplate, string textTemplate)
        {
            var mailMessage = new MailMessage();
            mailMessage.IsBodyHtml = true;
            mailMessage.Subject = mailObject.Subject;
            mailMessage.BodyEncoding = Encoding.UTF8;

            // Create the Plain Text version of the email
            mailMessage.Body = this.mergeTemplate(textTemplate, mailObject);

            // Create the HTML version of the email
            ContentType mimeType = new System.Net.Mime.ContentType("text/html");

            AlternateView alternate = AlternateView.CreateAlternateViewFromString(this.mergeTemplate(htmlTemplate, mailObject), mimeType);
            mailMessage.AlternateViews.Add(alternate);

            return mailMessage;
        }
    }

这是消息数据的一种情况:

    public class MessageData : IMailObject
    {
        public string Property1 { get; private set; }
        public string Property2 { get; private set; }
        public string Property3 { get; private set; }
        public string Property4 { get; private set; }
        public string Property5 { get; private set; }
        public string Property6 { get; private set; }
        public string Subject
        {
            get { return this.Property1 + DateTime.Now.ToShortDateString(); }
        }
        public List<MessageItemData> Items { get; private set; }

        public MessageData(string property1, string property2, string property3, DateTime property4, string property7, string property8, DateTime property9, DateTime property10, int property11, double property12, string property5, string property6)
        {
            this.Property1 = property1;
            this.Property2 = property2;
            this.Property3 = property3;
            this.Property4 = property4.ToShortDateString();
            this.Property5 = property5;
            this.Property6 = property6;

            this.Items = new List<MessageItemData>();
            this.Items.Add(new MessageItemData(property7, property8, property9, property10, property11, property12));
        }
    }

    public class MessageItemData
    {
        public string Property7 { get; private set; }
        public string Property8 { get; private set; }
        public string Property9 { get; private set; }
        public string Property10 { get; private set; }
        public int Property11 { get; private set; }
        public double Property12 { get; private set; }

        public MessageItemData( string property7, string property8, DateTime property9, DateTime property10, int property11, double property12)
        {
            this.Property7 = property7;
            this.Property8 = property8;
            this.Property9 = property9.ToShortDateString();
            this.Property10 = property10.ToShortDateString();
            this.Property11 = property11;
            this.Property12 = property12;
        }
    }

仅使用一组元素时,该功能有效。如果我们以MessageData类为例。所有信息都将被正确替换,但我想改进电子邮件生成器功能,因为此特定的MessageData类具有对象列表,其中Property7到Property12将被替换多次。

该函数从以下位置开始:if(operation ==“ endforeach”),但是我需要一些帮助来改进它,以便它可以通过以下方式运行:var items =(IEnumerable)value ;,以便该函数返回TemplateHeader + TemplateItem + TemplateItem + ...但是有许多TemplateItems + TemplateFooter。当前,即使列表中有多个项目,它也仅返回TemplateHeader + TemplateItem + TemplateFooter。

在这种情况下,我假设我需要获取列表项。我一直在尝试将其实施到下面的EmailGenerator中:

var items = (IEnumerable) value;

代码:

if (propertyInfo.PropertyType == typeof(List<>))
{
    foreach (var item in items)
    {
        Console.WriteLine(item);
    }
}

Console.WriteLine仅用于测试目的,以查看是否在Debug中获得了任何值(我目前正在获得空值)

1 个答案:

答案 0 :(得分:1)

假设在所有实例中 Items 属性的类型都是相同的,您可能想尝试使用 IsInstanceOfType 。然后通过 GetValue 方法获取属性的值。反射有时会造成混乱;),但希望这就是您要寻找的。

var data = new MessageData("a", "b", "c", DateTime.Now, "d", "e", DateTime.Now, DateTime.Now, 1, 2, "f", "g");
data.Items.Add(new MessageItemData("7", "8", DateTime.Now, DateTime.Now, 11, 12));
data.Items.Add(new MessageItemData("71", "81", DateTime.Now, DateTime.Now, 111, 112));

var dataType = data.GetType();
foreach (var propertyInfo in dataType.GetProperties())
{
    if (propertyInfo.PropertyType.IsInstanceOfType(data.Items))
    {
        foreach (var item in (List<MessageItemData>)propertyInfo.GetValue(data))
        {
            Console.WriteLine(item);
        }
    }
}