我试图使用泛型类型参数创建通用解析器,但我无法掌握100%的概念
private bool TryParse<T>(XElement element, string attributeName, out T value) where T : struct
{
if (element.Attribute(attributeName) != null && !string.IsNullOrEmpty(element.Attribute(attributeName).Value))
{
string valueString = element.Attribute(attributeName).Value;
if (typeof(T) == typeof(int))
{
int valueInt;
if (int.TryParse(valueString, out valueInt))
{
value = valueInt;
return true;
}
}
else if (typeof(T) == typeof(bool))
{
bool valueBool;
if (bool.TryParse(valueString, out valueBool))
{
value = valueBool;
return true;
}
}
else
{
value = valueString;
return true;
}
}
return false;
}
正如您可能猜到的,代码无法编译,因为我无法将int | bool | string转换为T(例如,value = valueInt)。感谢您的反馈,我甚至可能无法做到这一点。使用.NET 3.5
答案 0 :(得分:4)
XElement和XAttribute类都提供a set of explicit conversion operators(强制转换)以方便地将其内容转换为.NET基元类型。
例如,您可以执行以下操作:
XElement elem = // ...
string value1 = (string)elem.Attribute("myString");
int value2 = (int)elem.Attribute("myInt");
int? value3 = (int?)elem.Attribute("myOptionalInt");
bool value4 = (bool)elem.Attribute("myBool");
答案 1 :(得分:2)
不是最好的东西,但是如果你在物体上进行循环,你可以将你的T投射到别的东西,即首先投射到物体然后投射到T,反之亦然。我没有说你是否进入装箱/拆箱的东西,但编译器会接受这个。
答案 2 :(得分:2)
看到你只是写了一个伟大的if / then组合,我认为只要有一堆重载就会好一些:
public static class Parser
{
private static string TryParseCommon(XElement element, string attributeName)
{
if (element.Attribute(attributeName) != null && !string.IsNullOrEmpty(element.Attribute(attributeName).Value))
{
return element.Attribute(attributeName).Value;
}
return null;
}
public static bool TryParse(XElement element, string attributeName, out string value)
{
value = TryParseCommon(element, attributeName);
return true;
}
public static bool TryParse(XElement element, string attributeName, out int value)
{
return int.TryParse(TryParseCommon(element, attributeName), out value);
}
public static bool TryParse(XElement element, string attributeName, out bool value)
{
return bool.TryParse(TryParseCommon(element, attributeName), out value);
}
}
答案 3 :(得分:1)
在使用TypeConverter
之前我已经完成了Parse方法。
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
try
{
return (T)converter.ConvertFrom(value);
}
答案 4 :(得分:1)
这可能适合你。
private bool TryParse<T>(XElement element, string attributeName,out T value)
{
if (element.Attribute(attributeName) != null && !string.IsNullOrEmpty(element.Attribute(attributeName).Value))
{
string valueString = element.Attribute(attributeName).Value;
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
try
{
value = (T)converter.ConvertFrom(valueString);
return true;
}
catch
{
value = default(T);
return false;
}
}
value = default(T);
return false;
}
答案 5 :(得分:1)
答案 6 :(得分:1)
问题在于你正试图制作一些非常的泛型。即使您手动循环浏览自己可以解析的每种类型,也不会允许所有类型。
为什么不试试这个呢?首先定义一个描述一般TryParse
方法的委托:
public delegate bool TryParser<T>(string text, out T value);
然后重构您的方法,将其中一个作为参数:
// uglified code to fit within horizontal scroll area
public bool TryParse<T>
(XElement element, string attributeName, TryParser<T> tryParser, out T value)
{
value = default(T);
if (
element.Attribute(attributeName) != null &&
!string.IsNullOrEmpty(element.Attribute(attributeName).Value)
)
{
string valueString = element.Attribute(attributeName).Value;
return tryParser(valueString, out value);
}
return false;
}
现在,为所有标准类型重载这一点非常简单:
public bool TryParseInt(XElement element, string attributeName, out int value)
{
return TryParse<int>(element, attributeName, int.TryParse, out value);
}
public bool TryParseBool(XElement element, string attributeName, out bool value)
{
return TryParse<bool>(element, attributeName, bool.TryParse, out value);
}
等等。
这种方法的优点在于它甚至不会限制您使用where T : struct
约束,甚至是内置.NET类型。此解析器类的用户可以通过为他/她的自定义类型定义类似TryParse
的方法,从XML文档中解析出他/她自己的自定义类型。
答案 7 :(得分:1)
我过去使用的这种方法也可能有所帮助
public static T ChangeTypeTo<T>(this object value)
{
if (value == null)
return null;
Type underlyingType = typeof (T);
if (underlyingType == null)
throw new ArgumentNullException("value");
if (underlyingType.IsGenericType && underlyingType.GetGenericTypeDefinition()
.Equals(typeof (Nullable<>)))
{
var converter = new NullableConverter(underlyingType);
underlyingType = converter.UnderlyingType;
}
// Guid convert
if (underlyingType == typeof (Guid))
{
return new Guid(value.ToString());
}
// Check for straight conversion or value.ToString conversion
var objType = value.GetType();
// If this is false, lets hope value.ToString can convert otherwise exception
bool objTypeAssignable2typeT = underlyingType.IsAssignableFrom(objType);
// Do conversion
return (T) (objTypeAssignable2typeT ?
Convert.ChangeType(value, underlyingType)
: Convert.ChangeType(value.ToString(), underlyingType));
}