我有一个代表工厂传感器的类。由于历史原因,类似的对象(因此由同一个类表示)具有不同的标识:
为了适应这种情况,我使用了一个空接口:
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”而不是空接口,但是如何在id
类中键入sensor
属性?
答案 0 :(得分: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>
。
答案 1 :(得分:0)
我建议你在空接口中添加一个唯一标识符,该标识符应该在每个具体类中实现:
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; } }
}