这与我之前的一个问题有关 C# Generic List conversion to Class implementing List<T>
我有以下代码:
public abstract class DataField
{
public string Name { get; set; }
}
public class DataField<T> : DataField
{
public T Value { get; set; }
}
public static List<DataField> ConvertXML(XMLDocument data) {
result = (from d in XDocument.Parse(data.OuterXML).Root.Decendendants()
select new DataField<string>
{
Name = d.Name.ToString(),
Value = d.Value
}).Cast<DataField>().ToList();
return result;
}
这有效,但是我希望能够将 LINQ 查询的选择部分修改为如下所示:
select new DataField<[type defined in attribute of XML Element]>
{
Name = d.Name.ToString(),
Value = d.Value
}
这只是一个糟糕的方法吗?可能吗?有什么建议吗?
最佳答案
这是一个可行的解决方案:(您必须为 Type 属性指定完全限定的类型名称,否则您必须以某种方式配置映射...)
我使用了 dynamic 关键字,如果你没有 C# 4,你可以使用反射来设置值......
public static void Test()
{
string xmlData = "<root><Name1 Type=\"System.String\">Value1</Name1><Name2 Type=\"System.Int32\">324</Name2></root>";
List<DataField> dataFieldList = DataField.ConvertXML(xmlData);
Debug.Assert(dataFieldList.Count == 2);
Debug.Assert(dataFieldList[0].GetType() == typeof(DataField<string>));
Debug.Assert(dataFieldList[1].GetType() == typeof(DataField<int>));
}
public abstract class DataField
{
public string Name { get; set; }
/// <summary>
/// Instanciate a generic DataField<T> given an XElement
/// </summary>
public static DataField CreateDataField(XElement element)
{
//Determine the type of element we deal with
string elementTypeName = element.Attribute("Type").Value;
Type elementType = Type.GetType(elementTypeName);
//Instanciate a new Generic element of type: DataField<T>
dynamic dataField = Activator.CreateInstance(typeof(DataField<>).MakeGenericType(elementType));
dataField.Name = element.Name.ToString();
//Convert the inner value to the target element type
dynamic value = Convert.ChangeType(element.Value, elementType);
//Set the value into DataField
dataField.Value = value;
return dataField;
}
/// <summary>
/// Take all the descendant of the root node and creates a DataField for each
/// </summary>
public static List<DataField> ConvertXML(string xmlData)
{
var result = (from d in XDocument.Parse(xmlData).Root.DescendantNodes().OfType<XElement>()
select CreateDataField(d)).ToList();
return result;
}
}
public class DataField<T> : DataField
{
public T Value { get; set; }
}
关于c# - 使用 LINQ 创建一个 List<T> 其中 T : someClass<U>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8170295/