C# 如何在运行时使用 XElement 使用 Dynamic Linq 创建自定义(动态)类

标签 c# linq select dynamic xelement

您好,我正在尝试使用 XElement 和 DynamicLinq 列出通用/动态类,然后显示在 dataGridView1.DataSource 中

首先让我们使用 XElement 类创建 xml。

// 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();

它应该看起来像这样。

 - 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 - 

这一切都很好。但现在我遇到了我的问题 我想将此 xml 转换为“项目”类列表以添加到我的 dataGridView1.DataSource;

这有效,但不是通用的/动态的。

// 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 看起来像这样。对不起,没有图像,工作 block 一切:(

=============================================================
| Name          | Address                  | PropertyZ     |
=============================================================
| SCTGCITLTN    | NKMGDIYTGP LUCGNJCUNQ    | DYJJJGPZDH    |
| KBMZTYAMTS    | FZXDYVFAJO KVIMMNKSWG    | OLKTODAGLO    |
| APQPXOSANG    | NHQMYCIRWL QBHKZYKPXI    | UERMLHVXVL    |
| UIJZXZIFPY    | DDCESJZHHT PHHERLJUZS    | WHMKNQCMUB    |
| INPBWNBEIM    | QNGXVQKQRO NRXBXIUWRB    | DQAYPIBOPX    |
=============================================================

好的,这很好,但不是通用的/动态的, 然后我尝试的是这个。

// 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;

我收到以下错误消息。

No applicable method 'Element' exists in type 'XElement'

谁能帮我,

XElement_Root.Descendants("Item").AsQueryable().Select(selectQuery);

这样我就可以获得与使用 Normal Linq 时相同的结果。 谢谢。

最佳答案

我解决了我的问题。 不幸的是,使用 XElement 并不是最佳选择。

看完这篇文章,我有了新的想法。

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

首先让我们为动态类创建 Backbone

// 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;
        }
    }
}

和 nou 的魔法。

// 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;

就是这样。

再次感谢 Paolo,我希望这对其他人有帮助。

关于C# 如何在运行时使用 XElement 使用 Dynamic Linq 创建自定义(动态)类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10318277/

相关文章:

c# - Unity3D OnPointerClick 是基于凸轮位置?

linq - 当字段需要首先解析时,如何在 linq 查询中进行过滤?

mysql - mysql select 查询中多个字段的求和问题

c# - 以编程方式 Web 服务代理类的代理凭据

c# 将消息发送到 linux 上的本地 syslog 服务

c# - LINQ 表达式不遵守 xml 边界

R 过滤行 : where clause : from dataframe

php - 多个选择输入的数组

c# - 基于 .Net WebApi 的类型和属性的自定义 Json 序列化

c# - LINQ Max 扩展方法在空集合上出错