[英]Cast one dynamic to the type of another in c#
我正在尝试编写一个泛型函数,用于比较反射的预期结果(但是用户在配置中而不是在设计时提供期望值)与任意属性的实际结果进行比较。
我遇到了一个问题,其中默认情况下期望的类型并不总是反映返回的类型 - 例如我的反射结果(在动态中)可能是一个int,其中预期的结果是一个枚举成员(从int继承)。
我想,因此要做到以下几点:
if ((dCurrentValue as typeof(this.CheckValue)) != this.CheckValue) { oOut = false; }
但是,这似乎不起作用。 从网络上的笨拙,我已经设法发现System.Activator或Convert.ChangeType()可能是我的朋友。 然而,到目前为止,他们没有像我期望的那样工作 - 例如:
dCurrentValue = Convert.ChangeType(dCurrentValue, this.CheckValue.GetType());
Invalid cast from 'System.Int32' to 'Microsoft.Office.Core.MsoTriState'
抛出一个异常(对于提醒我这个问题的那一对) - 我知道这是错误的,因为:
(int)Microsoft.Office.Core.MsoTriState.msoTrue == -1 // true
((Microsoft.Office.Core.MsoTriState)(-1)) == Microsoft.Office.Core.MsoTriState.msoTrue // true
请注意,虽然我可以放入一个垫片来解决MsoTriState(即检查this.CheckValue的类型,以及显式转换,如果适用),我宁愿这样做也适用于未知的枚举条目。
编辑:感谢下面的评论,我在测试表单之前添加了一个测试:
if (((Type) this.CheckValue.GetType()).IsEnum)
{
dCurrentValue = Enum.Parse(this.CheckValue.GetType(), dCurrentValue.ToString());
}
这解决了我的直接问题。 我的猜测是结合Convert.ChangeType()
(正如我所提到的,似乎不喜欢将Enums转换为Ints)将涵盖大多数情况。
公共语言运行时类型( Boolean
, SByte
, Byte
...)实现IConvertible 。 Convert
仅适用于实现此接口的类型。 基类型之间的转换不是问题。 枚举不属于公共语言运行时类型,但它实现了IConvertible
。 这意味着您可以使用Convert.ChangeType
轻松地从Enum
转换为基本类型,但您不能简单地向后执行 - 这两种类型之间没有桥接 。 这就是为什么你Invalid cast from 'System.Int32' to 'Microsoft.Office.Core.MsoTriState'
捕获Invalid cast from 'System.Int32' to 'Microsoft.Office.Core.MsoTriState'
的原因。 IConvertible
包含方法( GetTypeCode
),它有助于获取有关Enum
基本类型的信息。 我写了一些代码来解决你的问题。
public static class Comparer
{
public static IConvertible CastToConvertible<T>(T value)
{
if (value is IConvertible)
{
return (IConvertible)Convert.ChangeType(value, ((IConvertible)value).GetTypeCode());
}
// this type is not supported
throw new ArgumentException("Unknown type: " + value.GetType());
}
public static bool Equals<T1, T2>(T1 first, T2 second)
{
try
{
IConvertible firstConveted = CastToConvertible(first);
IConvertible secondConverted = CastToConvertible(second);
// standard Equals cannot compare two different types,
// so here the second value is
// converted to the type of the first value
var secondChangedType = (IConvertible)Convert.ChangeType(
secondConverted, firstConveted.GetTypeCode());
return firstConveted.Equals(secondChangedType);
}
catch (Exception)
{
// an exception might be caught in two cases:
// 1. One of the values cannot be converted
// to IConvertible interface.
// 2. The second value cannot be converted
// to the type of the first value.
return false;
}
}
}
[TestClass]
public class ComparerTests
{
public enum ByteEnum : byte
{
One = 1, Two = 2
}
public enum IntEnum
{
One = 1, Two = 2, MegaLarge = 100500
}
[TestMethod]
public void EqualsTest()
{
Assert.IsTrue(Comparer.Equals(2, 2));
Assert.IsFalse(Comparer.Equals(1,2));
Assert.IsTrue(Comparer.Equals(1, IntEnum.One));
Assert.IsFalse(Comparer.Equals(1, IntEnum.Two));
Assert.IsTrue(Comparer.Equals(ByteEnum.One, IntEnum.One));
Assert.IsFalse(Comparer.Equals(ByteEnum.One, IntEnum.Two));
Assert.IsFalse(Comparer.Equals(ByteEnum.One, IntEnum.MegaLarge));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.