4

我正在使用 4.0,并试图通过开发一些用于类型转换的辅助方法来简化我的生活。以下方法运行良好。它将从任何字符串转换为其他数据类型。

System.ComponentModel;

public static T Convert<T>(string s)
{
      var typeConverter = TypeDescriptor.GetConverter(typeof(T));
      if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
      {
          return (T)typeConverter.ConvertFrom(s);
      }
      return default(T);
}

//calling this method...
var dateTime = MyConverter.Convert<DateTime>("13/07/2013");   // Date format "DD/mm/yyyy" 
// Working as expected... Taking "13" as Day, "07" as month

现在以下方法也在同一个类 MyConverter 中,但它不适用于 DateTime:

public static bool CanConvertTo<T>(string s)
{
     var typeConverter = TypeDescriptor.GetConverter(typeof(T));

     if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
     {
         return typeConverter.IsValid(s);
     }
     else
         return false;
}

这种方法的问题是,它只接受日期格式:“MM/dd/yyyy”

// This will give exception. It is taking "13" as month, "07" as Day
bool canConvert = MyConverter.CanConvertTo<DateTime>("13/07/2013");

编辑 根据 KeyboardP 的建议,我将方法更改为:

public static bool CanConvertTo<T>(string s)
{
    TypeConverter typeConverter;
    if (typeof(T) == typeof(DateTime))
    {
         typeConverter = new DateTimeConverter();
    }
    else
    {
        typeConverter = TypeDescriptor.GetConverter(typeof(T));
    }

    if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
    {
        return typeConverter.IsValid(s);
    }
    else
        return false;
}

并经过测试。测试结果是:

var date = MyConverter.Convert<DateTime>("13/07/2013");    //return perfect date
var canConvert = MyConverter.CanConvertTo<DateTime>("13/07/2013");  // returned false...

所以没有成功DateTimeConverter

4

2 回答 2

3

由于DateTime可以有许多不同的格式样式,我只使用DateTimeConverter而不是尝试在通用方法中重新创建它。

编辑

我做了一些ILspying,这就是我得出的结论(很高兴在任何一点上得到纠正)。

GetCoverter(typeof(DateTime))将返回一个DateTimeConverter所以调用CanConvertFrom实际上是调用DateTimeConverter.CanConvertFromCanConvertFrom调用base.CanConvertFrombase作为父 TypeConverter 类)。

base.CanConvertFrom方法如下所示

public virtual bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
    return sourceType == typeof(InstanceDescriptor);
}

因为DateTime.GetType() != typeof(InstanceDescriptor),返回值为falseCanConvertFromIsValid方法调用,因为我们刚刚建立了返回值false,所以IsValid返回false

那么Convert即使CanConvertFrom调用了相同的方法,该方法又是如何工作的呢?

好吧,您传递的参数是 type string,而不是DateTime

typeConverter.CanConvertFrom(typeof(string))

在上面的第一个代码片段中,该CanConvertFrom方法用于TypeConverter基类。如果我们看一下DateTimeConverter.CanConvertFrom覆盖,它看起来像这样

public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
    return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}

由于我们将 aString作为类型传入,因此此方法返回 true(与IsValid调用不同)。因为这返回true,所以代码继续调用

return (T)typeConverter.ConvertFrom(s);

(其中 T 是 a DateTime

简单地DateTimeConverter调用DateTime.Parse并忽略文化。我不确定这是设计使然还是错误,但DateTime.Parse除非您知道字符串始终具有相同的格式(或者您在调用方法之前正确格式化它),否则我不会依赖。

于 2013-07-04T10:42:53.723 回答
0

DateTimeConverter.IsValid 不使用当前文化。这就是我解决这个问题的方法

public class FixedDateTimeConverter : DateTimeConverter
{
    public override bool IsValid(ITypeDescriptorContext context, object value)
    {
        DateTime d;
        return DateTime.TryParse(value.ToString(), out d);
    }
}

...

var converter = TypeDescriptor.GetConverter(typeof (T));

if (typeof (T) == typeof (DateTime))
    converter = new FixedDateTimeConverter(); 

return converter.IsValid(null,r);
于 2017-12-01T14:01:08.513 回答