在多行字符串中使用枚举名称将每个字符串行与枚举的整数值相关联。有没有更好的办法?

问题描述 投票:0回答:1

我的RTF解析器需要处理两种rtf文件(每个程序执行一个文件):rtf文件保存自Word和rtf文件,由COTS报告生成器实用程序创建。每个rtf都有效,但不同。我的解析器使用正则表达式模式来检测,提取和处理两种类型的rtf文件中的各种rtf元素。

我决定在两个字典中实现rtf正则表达式模式列表,一个用于Word rtf文件所需的rtf正则表达式模式,另一个用于COTS实用程序rtf文件所需的rtf正则表达式模式。在运行时,我的解析器检测正在处理哪种类型的rtf文件(Word rtf包括rtf元素//schemas.microsoft.com/office/word而COTS rtf没有),然后从appopriate字典中获取所需的正则表达式模式。

为了在编写代码时简化引用模式的任务,我实现了一个枚举,其中每个枚举值代表一个特定的正则表达式模式。为了简化使模式与其对应的枚举保持同步的任务,我将正则表达式模式实现为here-string,其中每一行都是csv组合:{enum name}, {word rtf regex pattern}, {cots rtf regex pattern}。然后,在将模式加载到其字典中的运行时,我从csv获取枚举的int值并使用它来创建字典键。

这使得编写代码更容易,但我不确定它是实现和引用rtf表达式的最佳方法。有没有更好的办法?

示例代码:

public enum Rex {FOO, BAR};

string ex = @"FOO, word rtf regex pattern for FOO, cots rtf regex pattern for FOO
BAR, word rtf regex pattern for BAR, cots rtf regex pattern for BAR
";  

我加载这样的字典:

using (StringReader reader = new StringReader(ex))
{
    string line;

    while ((line = reader.ReadLine()) != null)
    {
        string[] splitLine = line.Split(',');
        int enumIntValue = (int)(Rex)Enum.Parse(typeof(Rex), splitLine[0].Trim());
        ObjWordRtfDict.Add(enumIntValue, line.Split(',')[1].Trim());
        ObjRtfDict.Add(enumIntValue, line.Split(',')[2].Trim());
    }
}

然后,在运行时,我根据解析器检测到的rtf文件的类型访问ObjWordRtfDict或ObjRtfDict。

string regExPattFoo = ObjRegExExpr.GetRegExPattern(ClsRegExExpr.Rex.FOO);

public string GetRegExPattern(Rex patternIndex)
{
    string regExPattern = "";

    if (isWordRtf)
    {
        ObjWordRtfDict.TryGetValue((int)patternIndex, out regExPattern);
    }
    else
    {
        ObjRtfDict.TryGetValue((int)patternIndex, out regExPattern);
    }

    return regExPattern;
}

修改了基于Asif建议的新代码

我保留了枚举模式名称,因此编译器可以检查对模式名称的引用

示例csv文件作为嵌入式资源包含在内

SECT,^\\pard.*\{\\rtlch.*\\sect\s\}, ^\\pard.*\\sect\s\}
HORZ_LINE2, \{\\pict.*\\pngblip, TBD

用法示例

string sectPattern = ObjRegExExpr.GetRegExPattern(ClsRegExPatterns.Names.SECT);

ClsRegExPatterns类

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace foo
{
    public class ClsRegExPatterns
    {
        readonly bool isWordRtf = false;
        List<ClsPattern> objPatternList;

        public enum Names { SECT, HORZ_LINE2 };

        public class ClsPattern
        {
            public string Name { get; set; }
            public string WordRtfRegex { get; set; }
            public string COTSRtfRegex { get; set; }
        }

        public ClsRegExPatterns(StringBuilder rawRtfTextFromFile)
        {
            // determine if input file is Word rtf or not Word rtf
            if ((Regex.Matches(rawRtfTextFromFile.ToString(), "//schemas.microsoft.com/office/word", RegexOptions.IgnoreCase)).Count == 1)
            {
                isWordRtf = true;
            }

            //read patterns from embedded content csv file
            string patternsAsCsv = new StreamReader((Assembly.GetExecutingAssembly()).GetManifestResourceStream("eLabBannerLineTool.Packages.patterns.csv")).ReadToEnd();

            //create list to hold patterns
            objPatternList = new List<ClsPattern>();

            //load pattern list
            using (StringReader reader = new StringReader(patternsAsCsv))
            {
                string line;

                while ((line = reader.ReadLine()) != null)
                {
                    string[] splitLine = line.Split(',');

                    ClsPattern objPattern = new ClsPattern
                    {
                        Name = splitLine[0].Trim(),
                        WordRtfRegex = splitLine[1].Trim(),
                        COTSRtfRegex = splitLine[2].Trim()
                    };

                    objPatternList.Add(objPattern);
                }
            }
        }

        public string GetRegExPattern(Names patternIndex)
        {
            string regExPattern = "";

            string patternName = patternIndex.ToString();

            if (isWordRtf)
            {
                regExPattern = objPatternList.SingleOrDefault(x => x.Name == patternName)?.WordRtfRegex;
            }
            else
            {
                regExPattern = objPatternList.SingleOrDefault(x => x.Name == patternName)?.COTSRtfRegex;
            }

            return regExPattern;
        }
    }
}
c# enums associations multilinestring herestring
1个回答
1
投票

如果我理解你的问题陈述;我宁愿喜欢下面这样的东西。

创建一个名为RtfProcessor的类

 public class RtfProcessor
        {
            public string Name { get; set; }
            public string WordRtfRegex { get; set; }
            public string COTSRtfRegex { get; set; }

            void ProcessFile()
            {
                throw new NotImplementedException();
            }

        }

其中name表示FOO或BAR等。您可以维护此类文件的列表,并继续填充csv文件,如下所示

List<RtfProcessor> fileProcessors = new List<RtfProcessor>();
            using (StringReader reader = new StringReader(ex))
            {
                string line;

                while ((line = reader.ReadLine()) != null)
                {
                    string[] splitLine = line.Split(',');
                    RtfProcessor rtfProcessor = new RtfProcessor();
                    rtfProcessor.Name = splitLine[0].Trim();
                    rtfProcessor.WordRtfRegex = line.Split(',')[1].Trim();
                    rtfProcessor.WordRtfRegex = line.Split(',')[2].Trim();
                    fileProcessors.Add(rtfProcessor);
                }
            }

并检索FOO或BAR的正则表达式模式

 // to get the regex parrtern for FOO you can use
  fileProcessors.SingleOrDefault(x => x.Name == "FOO")?.WordRtfRegex;

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.