【问题标题】:How to use reflection to link a const string field from one class to a readonly object field in another class如何使用反射将 const 字符串字段从一个类链接到另一个类中的只读对象字段
【发布时间】:2017-10-31 18:54:32
【问题描述】:

我有一个包含字符串常量的类和一个包含表示计数器对象的只读对象的类。我创建了一个自定义属性,该属性使用对应计数器的字符串表示来标记字符串常量。有没有一种使用属性将字符串 const 链接到计数器对象的好方法?

以下是字符串 const 的示例:

public static class OperatorDiagnosticsConstants
{
  [CounterType(CounterType = "ReagentProbe1")]
  public const string R1_PROBE_CODE = "SACT-158";
}

这是包含只读计数器对象的类:

public class MaintenanceCounterType : CounterTypeEnum
{
    public static readonly MaintenanceCounterType ReagentProbe1 = new MaintenanceCounterType(MaintenanceCounterTypeConstants.ReagentProbe1ID);
}

我可以想到两种解决方案,但想知道是否有更优雅的方法? 首先是在使用这两个类的代码中,我可以有一个带有 switch 语句的转换方法。开启属性字符串返回MaintenanceCounterType

public MaintenanceCounterType Convert(string attributeStr)
{
   switch (attributeStr)
   {
      case "ReagentProbe1":
        return MaintenanceCounterType.ReagentProbe1;
      ......
   }
  }

或者我想我可以将相同的自定义属性 CounterType 添加到 MaintenanceCounterType 并使用反射来匹配它们。我猜是通过检查自定义属性的字符串属性是否相等?

寻找更优雅的解决方案。谢谢!

【问题讨论】:

  • 你真正想解决什么问题?
  • 不清楚您要做什么。您是否可能尝试实现类似于注册表模式的目标?
  • “链接”究竟是什么意思?
  • @DanielA.Thompson - 我想我正在尝试解决可维护性问题。我提到的两种实现都可以工作,但在添加新计数器时需要相当多的开销。我试图找出一种更好的方法,然后是一个巨大的 switch 语句,从“R1_PROBE_CODE”字符串到 MaintenanceCounterType.ReagentProbe1。
  • @stephen.vakil - 我不熟悉这种模式,所以我会去看看。谢谢你的建议。我真正想做的就是找到一种更好的方法来从“R1_PROBE_CODE”获取相应的 MaintenanceCounterType.ReagentProbe1。不断添加新的“计数器”,并且不断添加到 switch 语句似乎有很多开销。我宁愿能够遍历每个类中的所有字段并将它们匹配起来。但我不确定这样做的干净方法。

标签: c# reflection enums


【解决方案1】:

您可以考虑使用 C# 枚举,而不是尝试使用这种方法,它在 API 中具有用于在枚举常量和字符串之间进行转换的功能。

将枚举常量转换为字符串 (API):

public class ConvertEnumToStringExample {
   enum Colors { Red, Green, Blue, Yellow };

   public static void Main() {

      Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
      Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), Colors.Yellow));
    }
}

将字符串转换为枚举常量 (API):

public class ConvertStringToEnumExample {
   enum Colors { Red, Green, Blue, Yellow };

   public static void Main() {

      string colorString = "Yellow";
      Colors colorValue = (Colors) Enum.Parse(typeof(Colors), colorString); 

      // colorValue is now Colors.Yellow

    }
}

【讨论】:

    【解决方案2】:

    改进的直接下降是使用nameof 运算符,以便链接在任何重构/重命名后仍然存在:

    [CounterType(CounterType = nameof(MaintenanceCounterType.ReagentProbe1)]
    public const string R1_PROBE_CODE = "SACT-158";
    

    convert 方法也可以按照您的建议使用反射来简化:

    public MaintenanceCounterType Convert(string attributeStr)
    {
        return typeof (MaintenanceCounterType).GetField(attributeStr);
    }
    

    话虽如此,在这些情况下,我首选的选择是将字符串常量替换为新类:

    public static class OperatorDiagnosticsConstant
    {
        public readonly string Value;
        public readonly MaintenanceCounterType CounterType;
    
        private OperatorDiagnosticsConstant(string value, MaintenanceCounterType counterType)
        {
            Value = value;
            CounterType = counterType;
        }
    
        public static OperatorDiagnosticsConstant R1_PROBE_CODE = new OperatorDiagnosticsConstant("SACT-158", MaintenanceCounterType.ReagentProbe1);
    }
    

    如果您想尝试保持与调用 OperatorDiagnosticsConstants.R1_PROBE_CODE 的现有代码的向后兼容性,您可以添加隐式字符串转换运算符:

    public static class OperatorDiagnosticsConstant
    {
        ...
    
        public override stirng ToString()
        {
            return Value;
        }
    
        public static implicit operator string(OperatorDiagnosticsConstant constant)
        {
            return constant.ToString();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多