对于这个问题的任何解决方案,似乎都有几个基本部分。
- 确保您正在比较相似的类型。
- 确保您可以比较该类型的实例。
这里有一些想法可以帮助您入门。为了清楚起见,我省略了一些错误检查。
认为:
Type type1 = dr1.Cells["SomeName"].ValueType;
Type type2 = dr2.Cells["SomeName"].ValueType;
然后看看你是否可以将一个值强制转换为另一个类型:
if (type1 != type2)
{
TypeConverter tc1 = TypeDescriptor.GetConverter(type1);
TypeConverter tc2 = TypeDescriptor.GetConverter(type2);
if (tc1.CanConvertFrom(type2))
{
cell2 = tc1.ConvertFrom(cell2);
type2 = type1;
}
else if (tc1.CanConvertTo(type2))
{
cell1 = tc1.ConvertTo(cell1, type2);
type1 = type2;
}
else if (tc2.CanConvertFrom(type1))
{
cell1 = tc2.ConvertFrom(cell1);
type1 = type2;
}
else if (tc2.CanConvertTo(type1))
{
cell2 = tc2.ConvertTo(cell2, type1);
type2 = type1;
}
else // fallback to string comparison
{
cell1 = tc1.ConvertToString(cell1);
type1 = cell1.GetType();
cell2 = tc2.ConvertToString(cell2);
type2 = cell2.GetType();
}
// cell1 and cell2 should be the same type now
}
现在您有了类似类型的实例,您需要找到一种方法来比较它们。
如果您使用的是 C# 4,那么 dynamic 关键字可能是您的朋友:
dynamic c1 = cell1;
try
{
int compareResult = c1.CompareTo(cell2);
}
catch(Exception)
{
// type1 doesn't implement an IComparable-like interface
}
如果您不使用 C# 4,您可以查看这些值是否实现IComparable
:
if (cell1 is IComparable)
{
int compareResult = ((IComparable)cell1).CompareTo(cell2);
}
或者它实现了一个泛型IComparable<T>
,在这种情况下可能需要使用一些反射技巧:
Type genericComparableType = typeof(IComparable<>);
Type typedComparableType = genericComparableType.MakeGenericType(new Type[] { type1 });
if (typedComparableType.IsInstanceOfType(cell1))
{
MethodInfo compareTo = typedComparableType.GetMethod("CompareTo", new Type[] { type1 });
int compareResult = (int)compareTo.Invoke(cell1, new object[] { cell2 });
}
最后,您可以Comparer<T>.Default
再次使用一些反射来查看是否可行:
Type genericComparerType = typeof(Comparer<>);
Type typedComparerType = genericComparerType.MakeGenericType(new Type[] { type1 });
PropertyInfo defaultProperty = typedComparerType.GetProperty("Default", BindingFlags.Static | BindingFlags.Public);
object defaultComparer = defaultProperty.GetValue(null, null);
MethodInfo compare = defaultComparer.GetType().GetMethod("Compare", new Type[] { type1, type1 });
int compareResult = (int)compare.Invoke(defaultComparer, new object[] { cell1, cell2 });
如果这些都不起作用,那么您将不得不回退到字符串比较。