我有一个类,我想用它来存储另一个类的"属性"。 这些属性只有名称和值。 理想情况下,我想要的是能够添加类型属性,以便返回的"值"始终是我想要的类型。
类型应该始终是原始的。 此类是一个抽象类的子类,它基本上将名称和值存储为字符串。 这个想法是这个子类将为基类添加一些类型安全性(以及节省我的一些转换)。
所以,我创建了一个类(大致)这个:
1 2 3 4 5 6 7 8
| public class TypedProperty<DataType> : Property
{
public DataType TypedValue
{
get { // Having problems here! }
set { base.Value = value.ToString();}
}
} |
所以问题是:
是否有一种"通用"方式从字符串转换回原语?
我似乎找不到任何通用的界面来连接整个转换(像ITryParsable这样理想!)。
我不确定我是否理解你的意图,但让我们看看这个是否有帮助。
1 2 3 4 5 6 7 8
| 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();}
}
} |
lubos hasko的方法因为无法控制而失败。以下方法适用于无效。不过,我没想出来。我通过Google找到了它:http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx归功于"Tuna Toksoz"
用法优先:
1
| TConverter.ChangeType< T >(StringValue); |
课程如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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)));
}
} |
对于许多类型(整数,双精度,日期时间等),有一个静态Parse方法。您可以使用反射调用它:
1 2 3 4 5 6
| MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );
if (m != null)
{
return m.Invoke(null, new object[] { base.Value });
} |
1
| TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value) |
TypeDescriptor是具有接受Type对象的方法GetConvertor的类,然后您可以调用ConvertFrom方法来转换该指定对象的value。
您可以使用诸如traits类之类的构造。通过这种方式,您将拥有一个参数化的辅助类,它知道如何将字符串转换为自己类型的值。然后你的getter可能看起来像这样:
1
| get { return StringConverter<DataType>.FromString(base.Value); } |
现在,我必须指出,我对参数化类型的体验仅限于C ++及其模板,但我想有一些方法可以使用C#泛型做同样的事情。
检查静态Nullable.GetUnderlyingType。
- 如果基础类型为null,则模板参数不是Nullable,我们可以直接使用该类型
- 如果基础类型不为null,则在转换中使用基础类型。
似乎为我工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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");
} |
从Bob的答案中获得灵感,这些扩展还支持空值转换和所有原始转换返回和第四。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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));
}
} |
例子
1 2 3 4 5
| string stringValue = null;
int? intResult = stringValue.Convert<int?>();
int? intValue = null;
var strResult = intValue.Convert<string>(); |
另一种变化。处理Nullables,以及字符串为null且T不可为空的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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(); }
}
} |
我使用了lobos答案,它的确有效。但由于文化设置的原因,我对双打转换有问题。所以我补充道
1
| return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture); |
1 2 3 4 5 6 7 8
| public class TypedProperty< T > : Property
{
public T TypedValue
{
get { return (T)(object)base.Value; }
set { base.Value = value.ToString();}
}
} |
我使用通过对象转换。这有点简单。