【问题标题】:C#: Converting unknown object to unknown type when object does not implement IConvertibleC#:当对象未实现 IConvertible 时将未知对象转换为未知类型
【发布时间】:2019-09-04 09:52:56
【问题描述】:

我有一个未知类型的对象 o。我还有一个类型 t 我想将我的对象转换成它。

object o = GetExampleObject();
Type t = GetExampleType();

当我尝试调用时:

Convert.ChangeType(o, t);

我得到错误:

对象必须实现 IConvertible。

有什么办法可以投吗?

【问题讨论】:

  • 唯一的方法是你可以将基类转换为继承类。您始终可以将变量转换为对象,然后将对象转换为类型。但通常你会得到运行时错误。其他方法是使用 Marshal StructToPtr 和 PtrToStruct。
  • 这似乎是一个 XY 问题。在什么情况下您实际上会发生这种情况?我打赌有比转换未知类型更好的方法来处理这个问题。
  • 另外,Convert.Invoke 是什么,您希望该功能做什么?您是否尝试过使用Convert.ChangeType?当您完成转换后,您会将结果存储在哪个变量中以及您将如何实际使用它?
  • 如果我们从问题中删除反射,如果您只能在代码中编写所有内容的确切类型,您是否有可以编译的示例类型和代码?我的意思是,您是否有类似(T)O cast 表达式或类似的东西,以便我们可以看到您要模仿的内容?你知道转换是否可能吗?

标签: c# .net reflection type-conversion


【解决方案1】:

为了将对象转换为仅在运行时上已知且没有IConvertibleType,您可以创建通用静态辅助方法:

public static T CastInto<T>(object obj)
{
    return (T)obj; 
    // return obj as T; // if you want to perform safe casting and you are ok with possible null values. Adding type constraint (e.g. where T : class) is needed to use it.
}

然后,你必须通过反射调用它:

var exampleType = GetExampleType();
MethodInfo castIntoMethod = this.GetType().GetMethod("CastInto").MakeGenericMethod(exampleType);

object o = GetExampleObject();
object castedObject = castIntoMethod.Invoke(null, new [] { o });

castedObject.GetType() == exampleType; // true

如果要转换的类型数量有限,我建议您缓存 MethodInfo 对象。

另外,请记住,动态方法调用既昂贵又缓慢。所以你可能想用它创建Delegate,使用CreateDelegatemethod

注意:正如 cmets 中正确指出的那样,在许多情况下,提出的解决方案不会简单地起作用。所以,只要你有不能相互转换的类型,你就会遇到运行时异常。

【讨论】:

  • 在某些情况下这是行不通的,例如如果obj 是盒装原始类型(CastInto&lt;long&gt;(5) 将抛出异常)。它也不适用于用户定义的转换,例如将string 转换为XName 时(CastInto&lt;XName&gt;("Test") 也会抛出,尽管(XName)"Test" 是有效的)。而castedObject.GetType() == exampleType 不一定是真的。
  • ...这个例子在哪里工作...然后没用因为castedObjectobject...这就是为什么问题是XY问题
  • @Selvin 绝对同意未正确指定需求这一事实。但是即使你有IConvertible,并且如果你可以使用Convert.ChangeType,你也会使用object,所以我认为这不是一个特别的问题——尤其是因为你不必知道在编译时间。
  • 如果没有正确指定需求,如何添加答案?
  • @DavidG 你认为所有对 SO 有答案的问题都被正确定义了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多