This is related to a prior question of mine C# Generic List conversion to Class implementing List<T>
I have the following code:
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;
}
This works however I would like to be able to modify the select portion of the LINQ query to be something like this:
select new DataField<[type defined in attribute of XML Element]>
{
  Name = d.Name.ToString(),
  Value = d.Value
}
Is this just a poor approach? is it possible? Any suggestions?
Here is a working solution: (You must specify fully qualified type names for your Type attribute otherwise you have to configure a mapping somehow...)
I used the dynamic keyword, you can use reflection to set the value instead if you do not have 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; }
}
                        You cannot do this easily in C#. The generic type argument has to specified at compile time. You can use reflection to do otherwise
             int X = 1;
            Type listype = typeof(List<>);
            Type constructed = listype.MakeGenericType(  X.GetType()  );
            object runtimeList = Activator.CreateInstance(constructed);
Here we have just created a List<int>. You can do it with your type
Different instances of a generic class are actually different classes.
I.e. DataField<string> and DataField<int> are not the same class at all(!)
This means, that you can not define the generic parameter during run-time, as it has to be determined during compile-time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With