Имеются следующие классы:
public class DeviceParameter
{
public string Key { get; set; }
public Guid DeviceId { get; set; }
public string Value { get; set; }
}
Устройство может иметь множество параметров разных типов, но все они хранятся в базе данных в виде строк.
public abstract class DeviceValueTypedParameter<TValue>
{
public string CodeName { get; }
public TValue Value { get; set; }
public Guid DeviceId { get; set; }
public DeviceValueTypedParameter(string codeName)
{
this.CodeName = codeName;
}
}
DeviceValueTypedParameter - это абстракция, имеющая типизированное значение ( TValue ) , используемая в C # значения параметра вместо используя строку, которую мы получаем из базы данных. Нет никакого наследования между DeviceValueTypedDeviceParameter и DeviceParameter, потому что я хочу сделать преобразование из TValue в строку по композиции.
public class ArmingStatusParameter : DeviceValueTypedParameter<ArmingStatuses>
{
public const string CODE_NAME = "ArmingStatus";
public ArmingStatusParameter() : base(CODE_NAME)
{
}
}
public enum ArmingStatuses
{
Unknown,
Armed,
Disarmed,
}
ArmingStatusParameter является примером типизированного параметра, который может существовать, где значением является Enum из ArmingStatuses. Другие типы, которые могут существовать: DateTimes, int32, double и т. Д.
Я уже выполнил преобразование из типизированного значения в строку, но сейчас я пытаюсь, как правильно выполнить преобразование из строкового в типизированное значение.
Пробовал разные подходы:
- явное или неявное преобразование
- Метод расширения
- Классы конвертера для каждого существующего типа
- Общий класс преобразователя на основе типа TValue
Вариант 1: прост в реализации, но нарушает POCO
ArmingStatusParameter. Люди могут забыть реализовать неявные / явные операторы, и ошибки будут происходить только во время компиляции.
Вариант 2: нарушает принцип сегрегации интерфейса (ISP), поскольку необходим для прямого доступа к преобразованию.
Вариант 3: он работает, но людям придется создавать много классов, и код будет слишком многословным. Для каждого отдельного параметра необходим экземпляр нового {X} TypedParameterConverter.
Вариант 4: кажется наилучшим вариантом, но у меня возникают проблемы "заставить его работать"
Я думал о чем-то вроде этого:
public interface IDeviceValueTypedParameterConverter
{
bool TryConvert<T, TValue>(DeviceParameter deviceParameter,
DeviceValueTypedParameter<TValue> deviceValueTypedParameter)
where T : DeviceValueTypedParameter<TValue>;
}
public class DeviceValueTypedParameterConverter : IDeviceValueTypedParameterConverter
{
public bool TryConvert<T, TValue>(DeviceParameter inputParameter,
DeviceValueTypedParameter<TValue> outputParameter)
where T : DeviceValueTypedParameter<TValue>
{
bool result = true;
if (inputParameter == null)
{
throw new NullReferenceException($"DeviceValueTypedParameter:'{typeof(T)}' must be initialized first");
}
if (inputParameter.Value is int)
{
result = int.TryParse(inputParameter.Value, out int temp);
outputParameter.Value = (TValue)temp;
}
else if (inputParameter.Value is Enum)
{
// some other code to convert the Enum's
}
// more else ifs one for each type
// (...)
else
{
result = false;
}
outputParameter.DeviceId = inputParameter.DeviceId;
return result;
}
}
Вопросы:
- Все Ифс дают мне предупреждение, гласящее: «Данное выражение никогда не бывает предоставленным».
- Невозможно сделать актерский состав (TValue). Он говорит, что не может конвертировать int в TValue. Единственное решение заключается в создании ценности с помощью отражения?