Dynamically choose which properties to get using L

2019-08-30 08:30发布

问题:

I have an MVC application with a dynamic table on one of the pages, which the users defines how many columns the table has, the columns order and where to get the data from for each field.

I have written some very bad code in order to keep it dynamic and now I would like it to be more efficient.

My problem is that I don't know how to define the columns I should get back into my IEnumerable on runtime. My main issue is that I don't know how many columns I might have.

I have a reference to a class which gets the field's text. I also have a dictionary of each field's order with the exact property It should get the data from.

My code should look something like that:

var docsRes3 = from d in docs
                       select new[] 
                       {  
                           for (int i=0; i<numOfCols; i++)
                           {
                               gen.getFieldText(d, res.FieldSourceDic[i]);
                           }
                       };

where:
docs = List from which I would like to get only specific fields
res.FieldSourceDic = Dictionary in which the key is the order of the column and the value is the property
gen.getFieldText = The function which gets the entity and the property and returns the value

Obviously, it doesn't work.

I also tried

StringBuilder fieldsSB = new StringBuilder();
        for (int i = 0; i < numOfCols; i++)
        {
            string field = "d." + res.FieldSourceDic[i] + ".ToString()";
            if (!string.IsNullOrEmpty(fieldsSB.ToString()))
            {
                fieldsSB.Append(",");
            }
            fieldsSB.Append(field);
        }


        var docsRes2 = from d in docs
                       select new[] { fieldsSB.ToString() };

It also didn't work.

The only thing that worked for me so far was:

List<string[]> docsRes = new List<string[]>();
        foreach (NewOriginDocumentManagment d in docs)
        {
            string[] row = new string[numOfCols];

            for (int i = 0; i < numOfCols; i++)
            {
                row[i] = gen.getFieldText(d, res.FieldSourceDic[i]);
            }

            docsRes.Add(row);
        }

Any idea how can I pass the linq the list of fields and it'll cut the needed data out of it efficiently?

Thanks, Hoe I was clear about what I need....

回答1:

Try following:

var docsRes3 = from d in docs
               select ( 
                   from k in res.FieldSourceDic.Keys.Take(numOfCols)
                   select gen.getFieldText(d, res.FieldSourceDic[k]));


回答2:

I got my answer with some help from the following link: http://www.codeproject.com/Questions/141367/Dynamic-Columns-from-List-using-LINQ

First I created a string array of all properties:

//Creats a string of all properties as defined in the XML
        //Columns order must be started at 0. No skips are allowed
        StringBuilder fieldsSB = new StringBuilder();
        for (int i = 0; i < numOfCols; i++)
        {
            string field = res.FieldSourceDic[i];
            if (!string.IsNullOrEmpty(fieldsSB.ToString()))
            {
                fieldsSB.Append(",");
            }
            fieldsSB.Append(field);
        }
        var cols = fieldsSB.ToString().Split(',');

        //Gets the data for each row dynamically
        var docsRes = docs.Select(d => GetProps(d, cols));

than I created the GetProps function, which is using my own function as described in the question:

private static dynamic GetProps(object d, IEnumerable<string> props)
    {
        if (d == null)
        {
            return null;
        }

        DynamicGridGenerator gen = new DynamicGridGenerator();
        List<string> res = new List<string>();

        foreach (var p in props)
        {
            res.Add(gen.getFieldText(d, p));
        }

        return res;
    }