c# - 使用 LINQ 创建一个 List<T> 其中 T : someClass<U>

标签 c# generics linq-to-xml

这与我之前的一个问题有关 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/

相关文章:

c# - C# 中的文件 - "file is used by another process"

java - BaseFoo 不能用不同的参数 : <T, X.Bar<T>> 和 <T,X.Foo<T>> 继承

java - 如何在java中转换为CRTP?

c# - XDocument Descendants 和 Element 总是返回空值

c# - 用于选择 XML 结构深处的元素的 LINQ 语句

xml - 为什么XDocument.Descendants()在PowerShell ISE中返回IEnumerator?

c# - ASP.NET 中的 GridView 不显示有或没有数据

c# - csv 文件导入 Azure 存储时出现数据格式问题

javascript - Vue 获取发布数据到 Controller asp.net mvc

c# - 如何在 C# 中使用泛型实现策略模式