【发布时间】:2019-09-05 16:07:57
【问题描述】:
有以下类:
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 是可以存在的类型化参数的示例,其中值是 ArmingStatuses 的枚举。其他可以存在的类型有 DateTimes、int32、double 等。
我已经完成了从类型值到字符串的转换,但是现在我正在努力如何正确地进行从字符串到类型值的转换。
尝试了不同的方法:
- 隐式或显式转换
- 扩展方法
- 存在的每种类型的转换器类
- 基于 TValue 类型的通用转换器类
方案一:容易实现,但违反了
的POCO
武装状态参数。人们可能会忘记实现隐式/显式运算符,错误只会在编译时发生。
选项 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;
}
}
问题:
- 所有 Ifs 都给我一个警告说:“给定的表达式永远不是提供的”。
- 无法进行强制转换 (TValue)。它说不能将 int 转换为 TValue。唯一的解决方案是通过反思创造价值?
【问题讨论】:
-
我认为您正在寻找 ISerializable 接口。在需要存储为文本的类中实现这一点。
-
只有属性值存储在字符串中,我在转换为字符串时没有问题,问题是当我检索此值时如何从 DeviceParameter 转换为 DeviceValueTypedParameter
从数据库。它们不是同一个类,这里不能使用序列化。 -
我会重新考虑您正在尝试做的事情,这样您甚至都没有尝试解决这个问题。听起来您已经确定了它导致的一些问题。你能重新考虑一下,让它是可序列化的吗?
-
DeviceParameter.Value必须始终是字符串,所以我看不出您的is测试如何工作?另外,您的 out 参数不需要out吗?DeviceParameter.Key是否提示您有关Value的类型? -
@ScottHannen 因为我无法更改数据库或值在数据库中的存储方式,所以我不知道在这种情况下如何使用序列化,即使如此,它也没有解决不了所有问题,只解决TValue转换问题。
标签: c# generics type-conversion