C# 测试 Convert.ChangeType 是否适用于两种类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1399273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Test if Convert.ChangeType will work between two types
提问by jeroenh
This is a follow-up to this questionabout converting values with reflection. Converting an object of a certain type to another type can be done like this:
这是关于使用反射转换值的问题的后续。可以像这样将某种类型的对象转换为另一种类型:
object convertedValue = Convert.ChangeType(value, targetType);
Given two Type instances (say FromType and ToType), is there a way to test whether the conversion will succeed?
给定两个 Type 实例(比如 FromType 和 ToType),有没有办法测试转换是否成功?
E.g. can I write an extension method like this:
例如,我可以编写这样的扩展方法:
public static class TypeExtensions
{
public static bool CanChangeType(this Type fromType, Type toType)
{
// what to put here?
}
}
EDIT: This is what I have right now. Ugly, but I don't see another way yet...
编辑:这就是我现在所拥有的。丑陋,但我还没有看到另一种方式......
bool CanChangeType(Type sourceType, Type targetType)
{
try
{
var instanceOfSourceType = Activator.CreateInstance(sourceType);
Convert.ChangeType(instanceOfSourceType, targetType);
return true; // OK, it can be converted
}
catch (Exception ex)
{
return false;
}
采纳答案by esac
I was just encountering this same issue, and I used Reflector to look at the source for ChangeType. ChangeType throws exceptions in 3 cases:
我刚刚遇到了同样的问题,我使用 Reflector 查看 ChangeType 的源代码。ChangeType 在 3 种情况下抛出异常:
- conversionType is null
- value is null
- value does not implement IConvertible
- 转换类型为空
- 值为空
- 值未实现 IConvertible
After those 3 are checked, it is guaranteed that it can be converted. So you can save a lot of performance and remove the try{}/catch{} block by simply checking those 3 things yourself:
勾选这3项后,保证可以转换。因此,您只需自己检查以下 3 件事,即可节省大量性能并移除 try{}/catch{} 块:
public static bool CanChangeType(object value, Type conversionType)
{
if (conversionType == null)
{
return false;
}
if (value == null)
{
return false;
}
IConvertible convertible = value as IConvertible;
if (convertible == null)
{
return false;
}
return true;
}
回答by Marc Wittke
Checking the method Convert.ChangeType in reflector I found this in the static constructor:
检查反射器中的方法 Convert.ChangeType 我在静态构造函数中发现了这一点:
ConvertTypes = new Type[] {
typeof(Empty), typeof(object), typeof(DBNull), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal),
typeof(DateTime), typeof(object), typeof(string)
};
In the end, this method is just checking either if the source is implementing IConvertible or if the target is one of the ConvertTypes above. So your method should look something like this (very rough):
最后,此方法只是检查源是否正在实现 IConvertible 或目标是否是上述 ConvertType 之一。所以你的方法应该是这样的(非常粗糙):
return (ConvertTypes.Contains(toType) || typeof(IConvertible).IsAssignableFrom(fromType));
回答by Brian
I have written a little framework that includes a Convert class that can do more than the System.Convert class. If you are interested in using it, you can download it from Github. It doesn't have the ability to determine if you can convert between values, but that seems like a good feature to add.
我编写了一个小框架,其中包含一个 Convert 类,它可以比 System.Convert 类做更多的事情。如果你有兴趣使用它,你可以从Github下载它。它无法确定您是否可以在值之间进行转换,但这似乎是一个很好的添加功能。
It does include the ability to convert values based on:
它确实包括基于以下内容转换值的能力:
- IConvertible
- TypeConverters
- ToXxx methods
- Parse static methods
- Parameterized constructor
- and a few other minor ones
- 敞篷车
- 类型转换器
- ToXxx 方法
- 解析静态方法
- 参数化构造函数
- 和其他一些次要的
回答by Immac
Based on what has already been answered on both questions I came up with this, (needs c#7)
基于已经回答的两个问题,我想出了这个,(需要 c#7)
public static object ChangeType(object value, Type conversion)
{
var type = conversion;
if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (value == null)
{
return null;
}
type = Nullable.GetUnderlyingType(type);
}
return Convert.ChangeType(value, type);
}
public static (bool IsSuccess, object Value) TryChangeType(object value, Type conversionType)
{
(bool IsSuccess, object Value) response = (false, null);
var isNotConvertible =
conversionType == null
|| value == null
|| !(value is IConvertible)
|| !(value.GetType() == conversionType);
if (isNotConvertible)
{
return response;
}
try
{
response = (true, ChangeType(value, conversionType));
}
catch (Exception)
{
response.Value = null;
}
return response;
}
}
Production code example:
生产代码示例:
public Item()
{
foreach (var pinfo in GetType().GetProperties())
{
object value = 0;
var response = ReflectionHelpers.TryChangeType(value, pinfo.PropertyType);
if(response.IsSuccess)
{
pinfo.SetValue(this, response.Value);
}
}
}
This starts all properties possible with 0.
这以 0 开始所有可能的属性。