C# How to Create a Custom (dynamic) class with Dynamic Linq using XElement in runtime

c#, dynamic, linq, select, xelement

Solution

I solved my Problem. Unfortunately using XElement was not the best choice.

I got a new idea after reading this post.

How do I create dynamic properties in C#? - Answered by Paolo Tedesco

First lets create the backbone for the Dynamic Class

// This is the class we are going to add to a List
public class DynamicClass
{
    // property is a class that will create dynamic properties at runtime
    private DynamicProperty _property = new DynamicProperty();

    public DynamicProperty property
    {
        get { return _property; }
        set { _property = value; }
    }
}

public class DynamicProperty
{
    // a Dictionary that hold all the dynamic property values
    private Dictionary<string, object> properties = new Dictionary<string, object>();

    // the property call to get any dynamic property in our Dictionary, or "" if none found.
    public object this[string name]
    {
        get
        {
            if (properties.ContainsKey(name))
            {
                return properties[name];
            }
            return "";
        }
        set
        {
            properties[name] = value;
        }
    }
}

and nou for the magic.

// create a List of String that are going to be our dynamic class's properties.
List<string> PropertyNames = new List<string>();
PropertyNames.Add("Name");
PropertyNames.Add("Age");
PropertyNames.Add("Phone");
PropertyNames.Add("Address");
PropertyNames.Add("City");

// Make a list of the DynamicClass
List<DynamicClass> DynamicClassList = new List<DynamicClass>();

// Adding 5 DynamicClass classes to the DynamicClassList
for (int cc = 0; cc < 5; cc++ )
{
    // declare a new DynamicClass
    var dynamicClass = new DynamicClass();

    // Give Random values to the New Properties. 
    // (because dynamicClass.property["xxx"] is of type object it could be anything.)
    // I'm just going to use random strings.
    foreach (String PropertyName in PropertyNames)
    {
        dynamicClass.property[PropertyName] = RandomString(5 + cc); // private string RandomString(int size)
    }

    // It could also have looked something like this. 

    // dynamicClass.property["Name"] = "Peter";
    // dynamicClass.property["Age"] = 25;
    // ....

    // Add the populated class to the list.
    DynamicClassList.Add(dynamicClass);
}

// Again I want the User to be able to select which fields (properties) they want to show in the DataGrid.
String selectQuery = GetSelectedFields(); // private string GetSelectedFields() { return ... }
// selectQuery will then be something like.
selectQuery = "new (property[\"Name\"] as Name, " +
    " property[\"Age\"] as Age, " +
    " property[\"Phone\"] as Phone, " +
    " property[\"Address\"] + \" \" + property[\"City\"] as Address)";

// Make a new DynamicClass that only contains the fields the user wants to see.
var newDynamicClasses = DynamicClassList.AsQueryable().Select(selectQuery);

// I Found that this was the easiest way to get the "var" back to a List, to add to the .DataSource
// because the IQueryable above does not have a .ToList();
List<object> newDynamicClassList = new List<object>();
foreach (var varDynamicClass in newDynamicClasses)
{
    newDynamicClassList.Add(varDynamicClass);
}

// populate the dataGridView1.DataSource with the New List of DynamicClass
dataGridView1.DataSource = newDynamicClassList;

and that is It.

Thx again to Paolo and I hope this helps someone else.

Problem

Hi I'm trying to make a list of a generic/dynamic class using XElement and DynamicLinq, to then show in a dataGridView1.DataSource First off lets make the xml by using the XElement class. ``` // a List of String that are going to be our dynamic class's properties. List<string> elements = new List<string>(); elements.Add("Name"); elements.Add("Address"); elements.Add("OtherElements1"); elements.Add("OtherElements2"); elements.Add("OtherElements3"); // XML Root Element XElement XElement_Root = new XElement("Root"); // Item Element, This is our dynamic class XElement XElement_Item = new XElement("Item"); // Insert the elements as XElements in the Item XElement // This is like defining our Properties to our Item Class foreach (String element in elements) { XElement_Item.Add(new XElement(element)); } // Add 5 "Item" classes to the List "Root" for (int cc = 0; cc < 5; cc++ ) { foreach (String elementName in elements) { // Adding a Random 10 length string to each "Item" Element(property) XElement_Item.Element(elementName).Value = RandomString(10); } // Adding the populated "Class"(Item) to the "List<>"(Root) XElement_Root.Add(new XElement(XElement_Item)); } // Preview of the created xml. String xml = XElement_Root.ToString(); ``` It should look something like this. ``` - Root - - Item - - Name - KJHLRGOUDM - /Name - - Address - QEOARCIIHO - /Address - - OtherElements1 - LYHNXEPZCU - /OtherElements1 - - OtherElements2 - MNSHTNYVXY - /OtherElements2 - - OtherElements3 - DETZKZPJCE - /OtherElements3 - - /Item - - Item - - Name - HYCNPMBTON - /Name - - Address - QOSIADMHGE - /Address - - OtherElements1 - ENLIKGEICX - /OtherElements1 - - OtherElements2 - OGXYNOKFRH - /OtherElements2 - - OtherElements3 - LEGJIPMKZH - /OtherElements3 - - /Item - ... - /Root - ``` This is all good. but now I get to my problem I want to turn this xml in to a List of Class "Item" to add to my dataGridView1.DataSource; This works but it is not generic / dynamic. ``` // Normal Linq !!! NOT GENERIC / DYNAMIC !!! var listOfClassItem = from classItem in XElement_Root.Descendants("Item") // "Item" is our class Name select new { Name = classItem.Element("Name").Value, Address = classItem.Element("Address").Value + " " + classItem.Element("OtherElements1").Value, PropertyZ = classItem.Element("OtherElements3").Value }; // populate the dataGridView1.DataSource with the New List of Class Item dataGridView1.DataSource = listOfClassItem.ToList(); ``` The Grid Then looks like this. Sorry no image, work blocks everyting :( ``` ============================================================= | Name | Address | PropertyZ | ============================================================= | SCTGCITLTN | NKMGDIYTGP LUCGNJCUNQ | DYJJJGPZDH | | KBMZTYAMTS | FZXDYVFAJO KVIMMNKSWG | OLKTODAGLO | | APQPXOSANG | NHQMYCIRWL QBHKZYKPXI | UERMLHVXVL | | UIJZXZIFPY | DDCESJZHHT PHHERLJUZS | WHMKNQCMUB | | INPBWNBEIM | QNGXVQKQRO NRXBXIUWRB | DQAYPIBOPX | ============================================================= ``` OK so this is nice but not generic / dynamic, what I then tried was this. ``` // Dynamic Linq now this should be more GENERIC / DYNAMIC // I want the User to be able to select which fields (properties) they want to show in the DataGrid String selectQuery = GetSelectedFields(); // private String GetSelectedFields() { return ...} // selectQuery will then be some thing like. selectQuery = " new ( Element(\"Name\").Value as Name, " + " Element(\"Address\").Value + \" \" + Element(\"OtherElements1\").Value as Address, " + " Element(\"OtherElements3\").Value as PropertyZ )"; // Then using Dynamic Linq to get the generic / dynamic class from the selection. // !!! THIS IS WHERE I'M STUCK !!! this does not work. :( var listOfClassItem2 = XElement_Root.Descendants("Item").AsQueryable().Select(selectQuery); // I Found that this was the easiest way to get the "var" back to a List, to add to the .DataSource // because the IQueryable above does not have a .ToList(); List<object> ListOfItem = new List<object>(); foreach (var varItem in listOfClassItem2) { ListOfItem.Add(varItem); } // populate the dataGridView1.DataSource with the New List of Class Dynamic Item dataGridView1.DataSource = ListOfItem; ``` I get the following Error message. ``` No applicable method 'Element' exists in type 'XElement' ``` can someone please help me with the, ``` XElement_Root.Descendants("Item").AsQueryable().Select(selectQuery); ``` so that I can get the same result as when I used the Normal Linq. Thx.

Original source

Related problems