【问题标题】:silverlight TypeDescriptor.GetConverter substitutesilverlight TypeDescriptor.GetConverter 替代
【发布时间】:2023-03-05 20:20:02
【问题描述】:

我正在尝试在silverlight 中使用LINQ to CSV 项目(它是一个很棒的项目),因为它是开源的,我想我可以重新编译为silverlight 类库,但不幸的是它似乎使用了silverlight 中没有的功能。 TypeDescriptor.GetConverter 方法。

它使用它来查找类型转换器以将 csv 列正确解析为相应的 CLR 类型。我对 linqtocsv 源进行更改以使其在 Silverlight 中工作没有问题,但我只是不知道 Silverlight 中的等效操作是什么。各种谷歌搜索把我带到了这个page,但只是说 XAML 解析器有办法做到这一点(但它没有说明如何访问这个功能)。

简而言之,问题是:

如何复制TypeDescriptor.GetConverter 的功能?

我不一定需要精确的替换,我只是想知道一种不用硬编码一堆类型类型转换器关联的好方法。

【问题讨论】:

    标签: c# silverlight type-conversion


    【解决方案1】:

    在轻型框架上,您的选择有限;我不会回避一点硬编码,特别是如果您只需要支持核心类型。它也将比完整的TypeConverter 选项更简单、更快。比如:

        static object Parse(Type type, string s)
        {
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.Boolean: return bool.Parse(s);
                case TypeCode.Byte: return byte.Parse(s);
                case TypeCode.Char: return s[0];
                case TypeCode.DateTime: return DateTime.Parse(s);
                    ...
            }
        }
    

    【讨论】:

    • 谢谢,我希望它不会发生这种情况,但我想这没什么大不了的......
    【解决方案2】:

    我已经构建了一个相当全面的工具集来解决这个问题。涉及的步骤很多,但这里是:

    1) 如果目标类型可从原始值赋值,则返回原始值 2)否则构造一个类型转换器(这里是有趣的部分)

    public static TypeConverter GetTypeConverter(Type type) 
    {
       TypeConverterAttribute attribute = (TypeConverterAttribute)Attribute.GetCustomAttribute(type, typeof(TypeConverterAttribute), false);
       if (attribute != null)
       {
         try 
         {
           var converterType = Type.GetType(attribute.ConverterTypeName, false);
           if (converterType != null) 
           {
             return (Activator.CreateInstance(converterType) as TypeConverter);
     }
         }
         catch {}
       }
       return new XamlStringConverter(type);
      }
    

    这里没有什么了不起的。但请注意,如果未找到转换器,则返回 XamlStringConverter。它利用 Xaml Parser 来转换事物。 type 字段包含在 Converter 中,并包含传递给构造函数的类型。

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
            var strValue = value as string;
            if (strValue != null) {
                if (this.type == typeof(bool)) {
                    return bool.Parse(strValue);
                }
                if (this.type.IsEnum) {
                    return Enum.Parse(this.type, stringValue, false);
                }
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append("<ContentControl xmlns='http://schemas.microsoft.com/client/2007' xmlns:c='" + ("clr-namespace:" + this.type.Namespace + ";assembly=" + this.type.Assembly.FullName.Split(new char[] { ',' })[0]) + "'>\n");
                stringBuilder.Append("<c:" + this.type.Name + ">\n");
                stringBuilder.Append(strValue);
                stringBuilder.Append("</c:" + this.type.Name + ">\n");
                stringBuilder.Append("</ContentControl>");
                ContentControl instance = XamlReader.Load(stringBuilder.ToString()) as ContentControl;
                if (instance != null) {
                    return instance.Content;
                }
            }
            return base.ConvertFrom(context, culture, value);
        }
    

    【讨论】:

    • 这看起来是一个很好的解决方案,除了it doesn't work。我的目标完全是用于原始类型的 TypeDescriptor.GetConverter 方法。
    • 我没有给你工作代码:这只是一些 sn-ps。例如,未定义 XamlStringConverter 类。我应该用完整的课程代码更新它吗?真的没那么复杂:创建一个 XamlStringConverter 类,一个带有 Type 参数的构造函数,以及一个由构造函数填充的类型字段。就这样。 (并检查我没有打错字。)
    • 我不需要 XamlStringConverter,我只想要一个反序列化的字符串输出。无论如何,我使用了the solution bellow,我更喜欢 TypeConverter 解决方案,因为它感觉更安全,但that 解决方案似乎对相当低的性能影响非常有效。
    【解决方案3】:

    如果您确定可以依赖一致性,请使用:

    private static object DeserializeValue(string value, Type type)
    {
      //uncomment if used with XML
      //value = HttpUtility.HtmlDecode(value);
      switch (Type.GetTypeCode(type))
      {
        case TypeCode.Empty:
          return null;
        case TypeCode.DBNull:
          return DBNull.Value;
        case TypeCode.Object:
          throw new InvalidCastException(
            string.Format("The type '{0}' is not supported.", type));
        case TypeCode.String:
          return value;
        default:
          {
            var convertible = value as IConvertible;
            return convertible.ToType(type, CultureInfo.InvariantCulture);
          }
      }
    }
    

    确保您的序列化函数与反序列化的文化相同以保持一致性:

    private static string SerializeValue(object value)
    {
      if (!(value is IConvertible))
        throw new InvalidCastException(
          string.Format("The type '{0}' is not supported.", value.GetType()));
      var convertible = (IConvertible)value;
      var str = convertible.ToString(CultureInfo.InvariantCulture);
      //uncomment if you're serializing to XML
      //return HttpUtility.HtmlEncode(str);
      return str;
    }
    

    请注意,仅支持原始类型。

    【讨论】:

      【解决方案4】:

      发件人:http://lostechies.com/jimmybogard/2010/02/19/automapper-for-silverlight-3-0-alpha/

      private static TypeConverter GetTypeConverter(Type type)
      {
          var attributes = type.GetCustomAttributes(typeof(TypeConverterAttribute), false);
      
          if (attributes.Length != 1)
              return new TypeConverter();
      
          var converterAttribute = (TypeConverterAttribute)attributes[0];
          var converterType = Type.GetType(converterAttribute.ConverterTypeName);
      
          if (converterType == null)
              return new TypeConverter();
      
          return Activator.CreateInstance(converterType) as TypeConverter;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-16
        • 2013-02-17
        • 1970-01-01
        相关资源
        最近更新 更多