从字符串中解析代码符号以构建枚举数组

时间:2017-12-28 07:39:25

标签: c# enums

我从远程设备获取数据,该设备发送包含单字母代码的状态字符串的数字数据。 我需要将字符串中的所有单字符状态代码映射到相应的枚举值,并将这些枚举值放入属性中,然后类消费者可以调用该属性来理解状态,而无需查找单字符状态代码。示例状态字符串是“... Q.D..B”。

是否有一种模式可以在不使用巨大的switch语句或多个if语句的情况下执行此操作?

注意:代码实际上包含了20多种状态,但为了简洁起见,我已对其进行了编辑。

[Flags]
public enum DataQuality
{
    Good = 0x0001,                           
    Questionable = 0x0004,                  
    NotCorrected = 0x0008,             
    BadEstimatedValue = 0x0010        
}

public class DataPointStatus
{
    private const string Good = "...";
    private const char Questionable = 'Q';
    private const char NotCorrected = 'D';
    private const char BadEstimatedValue = 'B';
    // Lot's more statuses...

    private readonly string _rawStatus;
    private readonly List<DataQuality> _statuses = new List<DataQuality>();

    public DataPointStatus(string rawStatus)
    {
        if (rawStatus == null)
        {
            throw new ArgumentNullException($"'{nameof(rawStatus)}' cannot be null.");
        }

        if (rawStatus.Trim() == string.Empty)
        {
            throw new ArgumentException($"'{nameof(rawStatus)}' cannot be an empty string.");
        }

        _rawStatus = rawStatus;

        SetStatusToGoodIfDataHasNoQualityErrors();
        if (!IsGood) SetBadQualityStatuses();
    }

    public bool IsGood => _statuses.Any(x => x == DataQuality.Good);
    public IEnumerable<DataQuality> Statuses => _statuses;

    private void CheckForGoodStatus()
    {
        if (_rawStatus == Good)
        {
            _statuses.Add(DataQuality.Good);
        }
    }

    private void SetStatusToGoodIfDataHasNoQualityErrors()
    {
        string status = _rawStatus.Replace(".", string.Empty);

        Start:
        switch (status)
        {
            case string s when s == "": return;

            case string s when s.Contains(Questionable):
                _statuses.Add(DataQuality.Questionable);
                status = status.Trim(Questionable);
                goto Start;

            case string s when s.Contains(NotCorrected):
                _statuses.Add(DataQuality.NotCorrected);
                status = status.Trim(NotCorrected);
                goto Start;

            case string s when s.Contains(BadEstimatedValue):
                _statuses.Add(DataQuality.BadEstimatedValue);
                status = status.Trim(BadEstimatedValue);
                goto Start;

            default:
                throw new ArgumentOutOfRangeException(
                    $"Invalid status code.");
        }
    }
}

3 个答案:

答案 0 :(得分:1)

您可以将枚举存储在字典中:

var dic = new Dictionary<string, DataQuality>(StringComparer.OrdinalIgnoreCase)
{
    ["G"] = DataQuality.Good,
    ["Q"] = DataQuality.Questionable,
    ["N"] = DataQuality.NotCorrected,
    ["B"] = DataQuality.BadEstimatedValue
};
string input = "Q";
if (dic.TryGetValue(input, out var status))
{
    // Use "status" variable here
}

答案 1 :(得分:1)

您可以使用正则表达式查找状态

//Regular expression can be more elaborated, 
//searching the status char in a concrete part of the string and so on
Regex regex = new Regex("Q|D|B"); 

然后是一个字典,用于将字符串值与相应的标记值

相匹配
Dictionary<string, DataQuality> qualities = InitializeDictionary();

这可以放在一个循环中。类似于while (rawStatus != "")

Match match = regex.Match(rawStatus);
if (match.Success) {
    _statuses.Add(qualities[match.Value]);
    rawStatus = regex.Replace(rawStatus, "");
}

答案 2 :(得分:1)

这不会直接适用于您的代码,因为您需要旗帜 要将字符串解析为枚举值列表,可以使用char枚举:

Enum MyEnum
{
    Good = 'g',
    Questionable = 'q',
    NotCorrected = 'n',
    BadEstimatedValue = 'b'
    //[...]
}

您可以使用Enum.TryParseParse将字符串转换为其枚举值 但对于一个char来说,需要一个简单的演员(MyEnum)myChar 这会将所有char转换为int值,即使它们未在枚举中定义  Enum.IsDefined将指示它是否存在于指定的枚举中。

对于char enum:

var input = "qngb###qnga";
var result = input.Where(x => Enum.IsDefined(typeof(toto), (int)x))
                  .Select(x => (toto)x);

结果:

  

可疑
  NotCorrected
  好
  BadEstimatedValue
  可疑
  NotCorrected
  好