What is the best way to make a LINQ-to-XML stateme

2019-03-04 04:57发布

问题:

I'm loading XML data into an object with this LINQ statement:

var smartFormFields = from smartFormField in xmlDoc.Descendants("smartFormField")
                      select new Models.SmartFormField
                      {
                          IdCode = smartFormField.Element("idCode").Value,
                          Label = smartFormField.Element("label").Value,
                          FieldType = smartFormField.Element("fieldType").Value,
                          DisplayStatus = smartFormField.Element("displayStatus").Value,
                          RequiredStatus = smartFormField.Element("requiredStatus").Value,
                          DisplayColumn = (int)smartFormField.Element("displayColumn"),
                          DisplayOrder = (int)smartFormField.Element("displayOrder"),
                          Description = smartFormField.Element("description").Value,
                          Example = smartFormField.Element("example").Value,
                          ControlType = smartFormField.Element("controlType").Value,
                          AutoSuggestDataSource = smartFormField.Element("autoSuggestDataSource").Value
                      };

However, my WHERE (and ORDERBY) statement will change each time, e.g.

it may be this:

var smartFormFields = from smartFormField in xmlDoc.Descendants("field")
                      where smartFormField.Element("IdCode").Value == "lastName"
                      select new Models.SmartFormField
                      {...

it may be this:

var smartFormFields = from smartFormField in xmlDoc.Descendants("field")
                      where (int)smartFormField.Element("DisplayOrder").Value > 50
                      select new Models.SmartFormField
                      {...

etc.

How can I put the Where statement into a variable, something like this:

PSEUDO-CODE:

string whereStatement = "where (int)smartFormField.Element(\"DisplayOrder\").Value > 50";

var smartFormFields = from smartFormField in xmlDoc.Descendants("field")
                      &&whereStatement
                      select new Models.SmartFormField
                      {...

回答1:

Do you have to express it as a string? If you're happy to supply it as a delegate, you can use:

// Just as one example of a where clause
Func<XElement, bool> whereClause = sff => (int) sff.Element("DisplayOrder").Value > 50;

var smartFormFields = xmlDoc.Descendants("field")
                            .Where(whereClause)
                            .Select(sff => 
                                new Models.SmartFormField
                                {
                                    IdCode = sff.Element("idCode").Value,
                                    ...
                                });

If you put this into a method, then you just need to use a lambda expression:

var fields = GetFormFields(sff => (int) sff.Element("DisplayOrder").Value > 50);

etc

That will let you easily supply different values for different calls, but you won't be able to just put the expressions into a text file without a bit more work. What are your real requirements here? Could you have a map of "filter name" to Func<XElement, bool>, and then read the filter names at execution time? Or do you really need it to be fully controlled at execution time, in an arbitrary way?

(Note that ordering is similar but probably slightly trickier... let's get the filtering sorted first.)