views:

88

answers:

1

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
                      {...
+2  A: 

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

Func<XElement, bool> whereClause = ...;

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

Jon Skeet
very interesting, requirements are: be able to parse various "load codes" from the constructor to load various groups from the XML file, so I will just have a switch statement that converts text into delegates, let build try to build this in...
Edward Tanguay
I'd just have a Dictionary<string, Func<XElement, bool>> and use that rather than a switch statement.
Jon Skeet