【问题标题】:How can I get rid of the empty interface used for a property如何摆脱用于属性的空接口
【发布时间】:2018-08-31 15:43:19
【问题描述】:

我有一个代表工厂传感器的类。由于历史原因,相似的对象(因此由同一类表示)具有不同的标识:

  • 有些有名字(即“north-west-gummy-bear”)
  • 有些有 areaId 和 sensorId

为了适应这一点,我使用了一个空接口:

public class sensor
{
    ISensorIdentifier id{get;set;}
}

public interface ISensorIdentifier{

}


public class namedSensorID:ISensorIdentifier{
    string name{get;set;}
}

public class idSensorID:ISensorIdentifier{
    int areaID{get;set;}
    int sensorID{get;set;}
}

这允许我对具有不同识别系统的对象使用相同的类。

据我了解,空接口是一种代码异味,我应该改用自定义属性。

但是,在阅读了自定义属性之后,我不知道从哪里开始。确实,我可以使用自定义属性 'sensorIdentifier' 而不是空接口,但我应该如何在 sensor 类中键入 id 属性?

【问题讨论】:

    标签: c# interface attributes


    【解决方案1】:

    你可以认为一个传感器有一个唯一的有效标识符信息(使用 c#7 原生元组支持):

    (Name, AreaId, SensorId)
    

    您的业务逻辑应强制要求有效的 id 信息必须是:

    (Name, null, null)
    

    或者

    (null, AreaId, SensorId)
    

    其他任何内容均无效。好的,让我们构建一个强制执行此操作的基类:

    public abstract class Sensor
    {
         private readonly string name;
         private readonly int? areaId, sensorId;
    
         protected Sensor(string name)
         {
             this.name = name;
         }
    
         protected Sensor(int areaId, int sensorId)
         {
             this.areaId = areaId;
             this.sensorId = sensorId;
         }
    
         public (string Name, int? AreaId, int? SensorId) Id
         {
              get
              {
                  Debug.Assert(
                      (name != null && !(areaId.HasValue || sensorId.HasValue)) ||
                      (name == null && (areaId.HasValue && sensorId.HasValue)));
                  return (name, areaId, sensorId);
              }
         }
    }
    

    您的特定传感器实现很简单,扩展 Sensor:

    public class NamedSensor: Sensor
    {
        public NamedSensor(string name)
            :base(name)
        { }
    }
    
    public class IdSensor: Sensor
    {
        public IdSensor(int areaId, int sensorId)
            :base(areaId, sensorId)
        { }
    }
    

    您可以愉快地使用IEnumerable<Sensor>。

    【讨论】:

    • 而对于低版本,只需使用自定义类型来表示id即可。
    【解决方案2】:

    我建议您在空接口中添加一个唯一标识符,该标识符应在每个具体类中实现:

    public interface ISensorIdentifier
    {
        string UniqueSensorId { get; }
    }
    

    您只需确保不同子类中的这些实现使这个新 ID 唯一。这是一个快速的建议:

    public class namedSensorID : ISensorIdentifier
    {
        public string UniqueSensorId { get { return nameof(namedSensorID) + name; } }
    
        string name { get; set; }
    }
    
    public class idSensorID : ISensorIdentifier
    {
    
        int areaID { get; set; }
        int sensorID { get; set; }
        public string UniqueSensorId { get { return nameof(idSensorID) + areaID + sensorID; } }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-12
      • 1970-01-01
      • 2011-10-17
      相关资源
      最近更新 更多