I am trying to use Dynamic LINQ Expressions with LINQ to XML, but having troubles with dynamic parameters.
Here's an example query from Dynamic LINQ Wiki:
var query = db.Customers
.Where("City == @0 and Orders.Count >= @1", "London", 10)
.OrderBy("CompanyName")
.Select("new(CompanyName as Name, Phone)");
In my case for example I am trying to query the following structure:
<DataCenter>
<Server IP="1.2.3.4">
<OS>Windows</OS>
</Server>
<Server IP="5.6.7.8">
<OS>Linux</OS>
</Server>
</DataCenter>
I am trying to read and parse it like this:
XElement XmlSource = XElement.Load(filePath)
var query = XmlSource.Elements().AsQueryable().Select("???????");
What do I put as a string parameter? For example if I try to retrieve IP and OS of all servers. When I try to use Element( )
or Attribute( )
methods of XElement I get error that "XElement doesn't have such property or method".
Though firstAtteibute
and firstNode
seems available. And something like this works:
var query = XmlSource.Elements()
.AsQueryable()
.Select("new (FirstAttribute.Value as IP, FirstNode.toString() as OS)");
Assuming you are using System.Linq.Dynamic.Core
, you can add XName
and XElement
to the accessible types so they will work:
public class MyCustomTypeProvider : DefaultDynamicLinqCustomTypeProvider {
public override HashSet<Type> GetCustomTypes() => new[] { typeof(XName), typeof(XElement) }.ToHashSet();
}
Since Dynamic LINQ doesn't use implicit conversions for method lookup, and doesn't understand explicit conversions, I showed two different ways to handle conversion of string
to XName
normally done by implicit conversion:
ParsingConfig.Default.CustomTypeProvider = new MyCustomTypeProvider();
var OSName = (XName)"OS";
var query = XmlSource.Elements().AsQueryable()
.Select("new (Attribute(XName.Get(\"IP\")).Value as IP, Element(@0).Value as OS)", OSName);
If it is possible for the element OS
to be missing, you must test for null
. Unfortunately, I have not been able to get the np
predicate to work:
var query = XmlSource.Elements().AsQueryable()
.Select("new (Attribute(XName.Get(\"IP\")).Value as IP, (Element(@0) != null ? Element(@0).Value : null) as OS)", OSName);