本文介绍了扩展 Convert.ChangeType 以根据请求生成用户定义的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定班级:

public class Foo
{
    public string Name { get; set; }
}

是否可以通过 Convert.ChangeType 从字符串创建 Foo 实例:

Is it possible to have a Foo instance created from a string through Convert.ChangeType:

Type type = typeof(Foo);
object value = "one";

value = System.Convert.ChangeType(value, type);

这就是第 3 方 API 尝试重建对象的方式.有人提到这可以通过隐式运算符实现,但据我了解,这将让我执行以下操作,而不是创建对象:

This is how a 3rd party API is attempting to rebuild objects. Someone mentioned this is possible with implicit operators, but from my understanding that will let me do the following, not create the object:

Foo foo = new Foo() { Name = "one" };
string fooAsString = foo;  // implicit conversion -- no cast needed

有没有办法以这种方式创建对象?另外,如果有其他方法,我确实可以更改 Convert.ChangeType.

Is there a way to create the object this way? Also, I do have the ability to change the Convert.ChangeType if there is another way to do this.

更新:我问的原因是因为它抛出异常:

Update: The reason I am asking is because it throws and exception:

从System.String"到的无效转换'JibbaJabba+Foo'.

添加运算符并没有解决问题.

and adding the operator did not resolve the issue.

推荐答案

根据MSDN 文档:

为了使转换成功,必须实现 IConvertible接口,因为方法简单包装对适当的调用IConvertible 方法.方法需要将 value 转换为支持conversionType.

Edit:在您的情况下,您似乎想将 from a string to a Foo.由于 string 类型(显然)没有在其 IConvertible 实现中定义到 Foo 的转换,我相信你不走运.

Edit: In your case, it seems that you want to convert from a string to a Foo. Since the string type (obviously) does not define a conversion to Foo in its IConvertible implementation, I believe you're out of luck.

更新:我不想建议你总是应该这样处理这类问题,但是......

Update: I don't want to suggest that this is how you should always approach this sort of problem, but...

我查看了 Convert.ChangeType 的代码反射器.它的长;我不会在这里复制它.但基本上它就像文档所说的那样:它在以下情况下有效:

I took a look at the code for Convert.ChangeType in Reflector. It's long; I won't reproduce it here. But basically it's doing as the documentation says: it only works if:

  • value 参数是实现 IConvertible 的类型的非空实例,或者:
  • value参数的类型和conversionType参数的类型相同(所以:Convert.ChangeType(myFoo, typeof(Foo)) 也可以,虽然没什么用).
  • The value parameter is a non-null instance of a type that implements IConvertible, or:
  • The type of the value parameter and the conversionType parameter are the same (so: Convert.ChangeType(myFoo, typeof(Foo)) would also work, though it'd be pretty useless).

然后,它循环遍历 IConvertible 支持的所有类型(显然不包括任何用户定义的类型)并最终使用 ToType 作为后备.

Then, it cycles through all the types supported by IConvertible (which obviously does not include any user-defined types) and ultimately uses ToType as a fallback.

所以,我们需要看看string类型对ToType的实现.

So, we need to look at the string type's implementation of ToType.

不幸的是,这是一条不幸的线:

Sadly, it is one unfortunate line:

return Convert.DefaultToType(this, type, provider);

DefaultToType 有什么作用?与 ChangeType 完全相同(减去 ToType 后备,显然是为了避免无限递归).

What does DefaultToType do? Exactly the same thing as ChangeType (minus the ToType fallback, obviously to avoid infinite recursion).

所以这根本行不通.

如果您完全依赖于在幕后使用 Convert.ChangeType 的第 3 方库,我建议您联系该库的开发人员并要求他们以某种方式扩展其 API,以允许你去完成你想要完成的事情.一些可能性可能是:

If you're absolutely tied to this 3rd party library that's using Convert.ChangeType behind the scenes, I would recommend contacting the library's developer and asking them to extend their API in some way that will allow you to accomplish what you're trying to accomplish. Some possiblities might be:

  • 按照 Ben Voigt 在评论中的建议,接受可选的 ConverterFunc 委托参数.
  • 接受 TypeConverter 参数
  • 接受某种类型的参数来实现像 IParser<T>
  • 这样的接口
  • Accepting an optional Converter<string, T> or Func<string, T> delegate parameter, as suggested by Ben Voigt in a comment.
  • Accepting a TypeConverter parameter
  • Accepting a parameter of some type that implements an interface like IParser<T>

无论如何,祝你好运.

这篇关于扩展 Convert.ChangeType 以根据请求生成用户定义的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 17:30