代码之家  ›  专栏  ›  技术社区  ›  blu

延伸转换.ChangeType根据请求生成用户定义的类型

  •  16
  • blu  · 技术社区  · 14 年前

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

    有没有可能通过一个字符串创建一个Foo实例转换.ChangeType:

    Type type = typeof(Foo);
    object value = "one";
    
    value = System.Convert.ChangeType(value, type);
    

    这就是第三方API试图重建对象的方式。有人提到隐式运算符可以实现这一点,但根据我的理解,这将允许我执行以下操作,而不是创建对象:

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

    有没有办法这样创建对象?而且,我有能力改变转换.ChangeType如果有别的办法的话。

    我之所以这么问是因为它抛出了

    “无效的强制转换自”系统字符串'到 “JibbaJabba+Foo”。

    4 回复  |  直到 14 年前
        1
  •  26
  •   Dan Tao    14 年前

    根据 the MSDN documentation :

    为了使转化成功, 必须实现IConvertible 接口,因为方法 IConvertible 价值 转换类型 得到支持。

    IConvertible 接口,它有一个 ToType 方法。你可以试试吗?(免责声明:我没有。这只是一个想法。)

    编辑 :在您的情况下,似乎要转换 string Foo 一串 类型(显然)没有定义到的转换 在它的 我相信你运气不好。


    更新

    Convert.ChangeType 在里面 Reflector 只有 在以下情况下工作:

    • 这个 value 易变的
    • 的类型 价值 conversionType 参数相同(因此: Convert.ChangeType(myFoo, typeof(Foo))

    然后,它遍历 易变的 (显然不包括任何用户定义的类型)并最终使用 ToType 作为退路。

    所以,我们需要看看 一串 类型的实现 总类型

    不幸的是,这是一句不幸的话:

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

    是什么 DefaultToType 你知道吗?完全一样 ChangeType (减去 总类型

    所以这根本行不通。

    如果你和这个第三方图书馆有联系 转换.ChangeType

    • 接受可选的 Converter<string, T> Func<string, T> 委托参数,正如Ben Voigt在评论中建议的那样。
    • TypeConverter 参数
    • 接受实现接口的某种类型的参数,如 IParser<T>

        2
  •  5
  •   Patko    14 年前

    直接从弦乐中选角并不像陶丹已经指出的那样有效。你能为这个字符串实现你自己的包装器并使用它吗?像这样的

    class MyString: IConvertible {
    
      public string Value { get; set; }
    
      ...
      object IConvertible.ToType(Type conversionType, IFormatProvider provider) {
        if (conversionType == typeof(Foo))
          return new Foo { Name = Value };
        throw new InvalidCastException();
      }
    
    }
    ...
    MyString myString = new MyString{Value="one"};
    Foo myFoo = (Foo)Convert.ChangeType(myString, typeof(Foo));
    

    不知道这是不是一个有用的主意,但无论如何。。

        3
  •  2
  •   MattP John    14 年前

    隐式运算符在这里不起作用?如果Foo是一个可以修改的类,那么我在过去使用过类似的东西,它还允许您将Foo实例与字符串进行比较。

    public class Foo
    {
      public string Name { get; set; }
    
      public static implicit operator Foo(string value)
      {
        return new Foo { Name = value };
      }
    }
    
    ...
    Foo foo = "fooTest";
    Console.WriteLine("Foo name: {0}", foo.Name);
    ...
    

    如果你必须使用ChangeType,那么据我所知,你运气不好。如果您可以修改API以使用TypeConverter,那么您可以使用如下内容。

    ...
    Type type = typeof(Foo);
    object value = "one";
    
    var converter = TypeDescriptor.GetConverter(type);
    if (converter.CanConvertFrom(value.GetType()))
    {
      object newObject = converter.ConvertFrom(value);
      Console.WriteLine("Foo value: {0}", newObject.ToString());
    }
    ...
    
    public class FooConverter : TypeConverter
    {
      public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
      {
        return sourceType == typeof(string);
      }
    
      public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
      {
        var name = value as string;
        if (name != null)
          return new Foo { Name = name };
        else
          return base.ConvertFrom(context, culture, value);
      }
    }
    
    [TypeConverter(typeof(FooConverter))]
    public class Foo
    {
      public string Name { get; set; }
    
      public override string ToString()
      {
        return Name;
      }
    }
    
        4
  •  0
  •   kofucii    14 年前

    object value1=“一”;

    Foo值2=(Foo) System.Convert.ChangeType(值,typeof(Foo));


    那么,如果您试图从字符串创建Foo类型,可以使用反射:

    String controlToCreate = "Foo";
    Type typeofControl = Type.GetType(controlToCreate,true);