Спасибо всем за ваши ответы.
Наконец, это решение, которое я выбрал для этой проблемы.Надеюсь быть полезным.Если у вас есть комментарии или вы знаете способ улучшить его без изменения структуры, дайте мне знать.
Сначала я создал интерфейс ISensor с минимальными требованиями.После этого я определил новый универсальный интерфейс ISensor следующим образом:
public delegate void SensorErrorEventHandler<TSensor>(TSensor sensor, ISensorError error)
where TSensor : ISensor;
public delegate void SensorReadingCompletedEventHandler<TSensor, TReading>(TSensor sensor, TReading[] read)
where TSensor : ISensor
where TReading : ISensorReading<TSensor>;
public interface ISensor : IDisposable
{
bool IsOpen { get; }
bool Started { get; }
void Connect();
void Disconnect();
void Start();
void Stop();
}
public interface ISensor<TSensor, TReading> : ISensor
where TSensor : ISensor
where TReading : ISensorReading<TSensor>
{
TReading[] LastReadings { get; }
event SensorErrorEventHandler<TSensor> Error;
event SensorReadingCompletedEventHandler<TSensor, TReading> ReadCompleted;
bool Read(out TReading[] readings);
}
public interface ISensorReading<TSensor> where TSensor : ISensor
{
TSensor Sensor { get; }
bool Mistaken { get; }
}
С этими интерфейсами, определенными и повторяющими те же структуры, я смог создать первую реализацию: класс TelemetricSensor с соответствующим ему ITelemetricReading
public delegate void TelemetricSensorThresholdExceededEventHandler<TSensor>(TSensor sensor)
where TSensor : ITelemetricSensor;
public interface ITelemetricSensor : ISensor
{
/* Properties, events and methods */
}
public interface ITelemetricReading : ISensorReading<ITelemetricSensor>
{
/* Properties, events and methods */
}
public abstract class TelemetricSensor<TSensor, TReading> : ITelemetricSensor, ISensor<TSensor, TReading>
where TSensor : ITelemetricSensor
where TReading : ITelemetricReading, ISensorReading<TSensor>
{
public abstract TReading[] LastReadings { get; }
public event SensorErrorEventHandler<TSensor> Error;
public event SensorReadingCompletedEventHandler<TSensor, TReading> ReadCompleted;
public abstract bool Read(out TReading[] readings);
}
Здесь интересен TReading абстрактного класса TelemetricSensor.Он определен как
TReading : ITelemetricReading, ISensorReading<TSensor>
, что может показаться избыточным, поскольку ITelemetricReading наследуется от ISensorReading, но требуется для получения кода, скомпилированного и удовлетворяющего требованию как для свойства
TReading[] LastReadings { get; }
и
bool Read(out TReading[] readings);
метод.Наконец, чтобы пропустить утомительное приведение (и, возможно, некоторые ошибки), можно выполнить многократные перегрузки Read (...), чтобы каждый из них предоставил правильно приведенные данные и также соответствовал всем реализациям интерфейса.