泛型类型转换FROM字符串

我有一个类,我想用它来存储另一个类的“属性”。这些属性只有一个名称和一个值。理想情况下,我希望能够添加输入属性,以便返回的“值”始终是我想要的类型。

类型应该始终是原语。这个类继承了一个抽象类,这个抽象类基本上将名称和值存储为字符串。这个想法是,这个子类将向基类添加一些类型安全(以及节省一些转换)。

所以,我创建了一个类,大致是这样的:

public class TypedProperty<DataType> : Property
{
public DataType TypedValue
{
get { // Having problems here! }
set { base.Value = value.ToString();}
}
}

所以问题是:

是否有一种“通用”的方法从字符串转换回原语?

我似乎找不到任何通用的接口来链接整个转换(像ITryParsable这样的东西会是理想的!)。

163046 次浏览

你可以使用诸如特性类这样的构造。通过这种方式,您将拥有一个参数化的帮助类,它知道如何将字符串转换为自己类型的值。然后你的getter可能是这样的:

get { return StringConverter<DataType>.FromString(base.Value); }

现在,我必须指出,我对参数化类型的经验仅限于c++及其模板,但我想象有一些方法可以使用c#泛型来做同样的事情。

我不确定我是否正确理解了你的意图,但让我们看看这个是否有用。

public class TypedProperty<T> : Property where T : IConvertible
{
public T TypedValue
{
get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
set { base.Value = value.ToString();}
}
}

对于许多类型(integer, double, DateTime等),都有一个静态Parse方法。你可以使用反射调用它:

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );


if (m != null)
{
return m.Invoke(null, new object[] { base.Value });
}

Lubos hasko的方法对空值无效。下面的方法将适用于可空值。不过这不是我想出来的。我发现它通过谷歌:http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx信用“金枪鱼Toksoz”

用法:

TConverter.ChangeType<T>(StringValue);

班级在下面。

public static class TConverter
{
public static T ChangeType<T>(object value)
{
return (T)ChangeType(typeof(T), value);
}


public static object ChangeType(Type t, object value)
{
TypeConverter tc = TypeDescriptor.GetConverter(t);
return tc.ConvertFrom(value);
}


public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
{


TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
public class TypedProperty<T> : Property
{
public T TypedValue
{
get { return (T)(object)base.Value; }
set { base.Value = value.ToString();}
}
}

我通过一个对象使用转换。它更简单一点。

TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor是具有方法GetConvertor的类,该方法接受一个Type对象,然后你可以调用ConvertFrom方法来转换该指定对象的value

我用了lobos的答案,它工作。但是由于区域性设置,我在双打的转换中遇到了一个问题。所以我补充道

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);

检查静态Nullable.GetUnderlyingType。 —如果基础类型为空,则模板形参不是Nullable,可以直接使用该类型 —如果底层类型不为空,则使用底层类型进行转换

似乎对我有用:

public object Get( string _toparse, Type _t )
{
// Test for Nullable<T> and return the base type instead:
Type undertype = Nullable.GetUnderlyingType(_t);
Type basetype = undertype == null ? _t : undertype;
return Convert.ChangeType(_toparse, basetype);
}


public T Get<T>(string _key)
{
return (T)Get(_key, typeof(T));
}


public void test()
{
int x = Get<int>("14");
int? nx = Get<Nullable<int>>("14");
}

这是另一种变化。处理可空值,以及字符串为空且T为可空值的情况。

public class TypedProperty<T> : Property where T : IConvertible
{
public T TypedValue
{
get
{
if (base.Value == null) return default(T);
var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
return (T)Convert.ChangeType(base.Value, type);
}
set { base.Value = value.ToString(); }
}
}

受到鲍勃答案的启发,这些扩展还支持空值转换和所有原语转换。

public static class ConversionExtensions
{
public static object Convert(this object value, Type t)
{
Type underlyingType = Nullable.GetUnderlyingType(t);


if (underlyingType != null && value == null)
{
return null;
}
Type basetype = underlyingType == null ? t : underlyingType;
return System.Convert.ChangeType(value, basetype);
}


public static T Convert<T>(this object value)
{
return (T)value.Convert(typeof(T));
}
}

例子

            string stringValue = null;
int? intResult = stringValue.Convert<int?>();


int? intValue = null;
var strResult = intValue.Convert<string>();

你可以在一行中完成如下:

YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));

快乐编码;)