我正在尝试编写一个类来解析带有值字符串的XML配置文件到相应的值和类型。配置的示例条目是:
a<?php
$query = "SELECT * FROM aliases where client_id='$userid' ORDER BY time_edit DESC";
$result = mysql_query($query);
if ($result->num_rows > 0) {
echo "<table border=1>";
echo "<tr align=center>";
echo "<th width=25%>Alias</th>";
echo "<th width=25%>Times Used</th>";
echo "<th width=25%>First Used</th>";
echo "<th width=25%>Last Used</th>";
echo "</tr>";
echo "<tr><td>No Results</td></tr>";
}
echo "<table border=1>";
echo "<tr>";
echo "<th width=25%>Alias</th>";
echo "<th width=25%>Times Used</th>";
echo "<th width=25%>First Used</th>";
echo "<th width=25%>Last Used</th>";
echo "</tr>";
$countRow = 0;
$class = 1;
while ($row = mysql_fetch_assoc($result)) {
$countRow += 1;
$timesused=$row['num_used'];
$alias=$row['alias'];
$alias=htmlentities($alias);
$firstused=$row['time_add'];
$firstused = date('d M Y H:i:s', $firstused);
$lastused=$row['time_edit'];
$lastused = date('d M Y H:i:s', $lastused);
echo "<tr align=center>";
echo "<td class='visible".$class.">$alias</td>";
echo "<td class='visible".$class.">$timesused</td>";
echo "<td class='visible".$class.">$firstused</td>";
echo "<td class='visible".$class.">$lastused</td>";
echo "</tr>";
if($countRow == 50){ $class += 1; $countRow = 0; }
}
echo "</table>";
?>
我现在想写一个函数来解析我的值,这样我就可以这样做:
<ConfigItem Name="ParameterName" Value="1.3" Type="Double"/>
最初我尝试使用其返回类型重载double value = GetItemValue("//ConfigItem[@Name='ParameterName']");
,但这在C#中是不可能的。我现在尝试使用泛型函数,以便我这样做:
GetItemValue
我试图写的功能是这样的:
double value = GetItemValue<double>("//ConfigItem[@Name='ParameterName']");
不幸的是,这不起作用,我收到以下错误:
public T GetItemValue<T>(string configName)
{
list = XmlConfig.SelectNodes(configName);
T returnValue;
if (T.TryParse(list[0].Attributes["Value"].Value, out returnValue))
return returnValue;
else
throw new InvalidProgramException("Could not parse: " + configName);
}
我不确定问题是什么,但我怀疑,它必须考虑到这样一个事实,即在编译时不清楚所有类型Error CS0119 'T' is a type parameter, which is not valid in the given context
是否都有方法T
。我尝试使用像TryParse
这样的约束来解决这个问题,但C#约束不支持ValueTypes。
那么问题是什么,我该如何实现,我想做什么?请注意,对于将来我还需要where T : Int, Double
的自定义类型的任何建议。
答案 0 :(得分:0)
假设您只需要标准的内置基元类型,那么您可以使用Convert或其他内容。
但是如果您需要支持自定义类型,则可以使用TypeConverter。这是一种笨重的方式,但可能是最正确的。 (虽然老实说我从来没有完全尝试过它)
如果你不想搞砸TypeConverter
,你可以随时使用这样的东西,假设你的自定义类型采用静态Parse(String)
方法:
public class Value
{
private readonly Int32 _value;
public Value(Int32 value)
{
this._value = value;
}
public override String ToString()
{
return String.Format("Value {0}", this._value);
}
public static Value Parse(String str)
{
return new Value(Int32.Parse(str));
}
}
public class Converter
{
private readonly IDictionary<Type, Func<String, Object>> _parseFunctions;
public Converter()
{
this._parseFunctions = new Dictionary<Type, Func<String, Object>>();
}
public T Convert<T>(String str)
{
Func<String, Object> parse;
if (this._parseFunctions.TryGetValue(typeof(T), out parse))
{
return (T)parse(str);
}
var parseMethodInfo = typeof(T)
.GetMethod(
name: "Parse",
bindingAttr: BindingFlags.Static | BindingFlags.Public,
binder: null,
types: new[] { typeof(String) },
modifiers: null);
if (parseMethodInfo != null)
{
var parameters = new [] { Expression.Parameter(typeof(String)) };
parse = Expression
.Lambda<Func<String, Object>>(
Expression.Convert(
expression: Expression.Call(null, parseMethodInfo, parameters),
type: typeof(Object)),
parameters: parameters)
.Compile();
this._parseFunctions.Add(typeof(T), parse);
return (T)parse(str);
}
return (T)System.Convert.ChangeType(str, typeof(T));
}
}
public static void Main()
{
try
{
var converter = new Converter();
Console.WriteLine(converter.Convert<Int32>("123"));
Console.WriteLine(converter.Convert<Double>("123.32"));
Console.WriteLine(converter.Convert<Value>("500"));
Console.WriteLine(converter.Convert<Value>("600"));
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}