Генератор электронной почты итерация через список - PullRequest
1 голос
/ 20 июня 2019

Я написал функцию, которая генерирует электронное письмо в формате HTML и заполняет его информацией из базы данных.

Я пытался перебрать список, но не могу заставить эту функциюбыть универсальным и запускаться через список элементов.

Вот функция генератора электронной почты.Он достаточно универсален, поэтому его можно использовать в самых разных шаблонах электронной почты.

    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);, чтобы функция возвращала 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 Ответ

1 голос
/ 20 июня 2019

Предполагая, что тип свойства 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);
        }
    }
}
...