实现不可转换接口
本文关键字:接口 可转换 实现 | 更新日期: 2023-09-27 18:15:18
我有自定义类型LocalizedString,我需要实现IConvertible接口,因为当我们序列化类型到我们的DB时,我们使用Convert。更改类型,我不能更改这部分代码。
我所做的就是实现:
string IConvertible.ToString(IFormatProvider provider)
{
return string.Format(this.ToString());
}
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
return Convert.ChangeType(this.ToString(), conversionType);
}
public TypeCode GetTypeCode()
{
return TypeCode.Object;
}
和我留下的所有其他方法NotImplementedException,因为我没有任何合理的转换到其他类型。(我最终会让他们抛出InvalidCastException,但那是另一个故事。)
然而,当我调用Convert.ChangeType(val, pr.__property.PropertyType)
时,我仍然收到val = ""
, pr.__property.PropertyType = {Name = "LocalizedString" FullName = "Sampo.CMS.LocalizedString"}
代码崩溃:
从'System '强制转换无效。String' to 'Sampo.CMS.LocalizedString'.
我还需要做什么?
如果你在看MSDN系统。在IConvertable的例子中,你会看到他们使用了Convert。在它们的实现中更改类型,但那是因为它们传递了要转换的double类型。转换。ChangeType不知道如何转换自定义对象类型。我很确定你需要在里面实现转换,比如:
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
if (conversionType == typeof(Sampo.CMS.LocalizedString))
{
// Do your conversion here and return the string.
return this.ToString() + "!!!!";
}
throw new InvalidCastException($"Converting type '"{typeof(LocalizedString )}'" to type '"{conversionType.Name}'" is not supported.");
}
实际上,对于你必须实现的其余16个方法,你可能也可以为它们抛出invalidcastexception…
还有,你在IConvertable中使用string.Format(this.ToString())有什么原因吗?ToString实现吗?你没有传递任何参数,所以它不应该只是返回this.ToString()吗?
这里有一些可能有用的链接:
c# .NET中使用IConvertible接口的类型转换示例系统。从某个版本转换源代码。它有Convert的源代码。所以你可以看看它到底在做什么以及为什么它不起作用
基于Brent Rittenhouse的答案的IConvertible
的完整实现。
public struct TableAddress : IConvertible
{
/*....*/
#region IConvertible Implementation
static T ThrowNotSupported<T>()
{
var ex = ThrowNotSupported(typeof(T));
return (T)ex;
}
static object ThrowNotSupported(Type type)
{
throw new InvalidCastException($"Converting type '"{typeof(TableAddress)}'" to type '"{type}'" is not supported.");
}
TypeCode IConvertible.GetTypeCode()
{
return TypeCode.Object;
}
bool IConvertible.ToBoolean(IFormatProvider provider) => ThrowNotSupported<bool>();
char IConvertible.ToChar(IFormatProvider provider) => ThrowNotSupported<char>();
sbyte IConvertible.ToSByte(IFormatProvider provider) => ThrowNotSupported<sbyte>();
byte IConvertible.ToByte(IFormatProvider provider) => ThrowNotSupported<byte>();
short IConvertible.ToInt16(IFormatProvider provider) => ThrowNotSupported<short>();
ushort IConvertible.ToUInt16(IFormatProvider provider) => ThrowNotSupported<ushort>();
int IConvertible.ToInt32(IFormatProvider provider) => ThrowNotSupported<int>();
uint IConvertible.ToUInt32(IFormatProvider provider) => ThrowNotSupported<uint>();
long IConvertible.ToInt64(IFormatProvider provider) => ThrowNotSupported<long>();
ulong IConvertible.ToUInt64(IFormatProvider provider) => ThrowNotSupported<ulong>();
float IConvertible.ToSingle(IFormatProvider provider) => ThrowNotSupported<float>();
double IConvertible.ToDouble(IFormatProvider provider) => ThrowNotSupported<double>();
decimal IConvertible.ToDecimal(IFormatProvider provider) => ThrowNotSupported<decimal>();
DateTime IConvertible.ToDateTime(IFormatProvider provider) => ThrowNotSupported<DateTime>();
string IConvertible.ToString(IFormatProvider provider) => ThrowNotSupported<string>();
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
if (conversionType == typeof(TableAddress))
{
return this;
}
// Other implementations here
return ThrowNotSupported(conversionType);
}
#endregion
/*....*/
}