Reputation: 1503
I'm trying to build a repository that takes a generic type and returns a generic IQueryable. I have it running when the data source is a db table. I want to do the same thing when the data source is an XML document, but I can't get it to work.
Here's the code:
public IQueryable<T> GetAll()
{
XElement xml = XElement.Load(this.url);
IQueryable<T> nodes = null;
nodes = (
from c in xml.Nodes().Cast<T>()
select c).AsQueryable<T>();
return nodes;
}
Here's the error (which by the way occurs at runtime, not compile):
Unable to cast object of type 'System.Xml.Linq.XElement' to type 'X'
Thanks in advance for your response.
Upvotes: 1
Views: 755
Reputation: 125650
Are you looking for a solution which would automagically translate XML document into your custom class? There is nothing like that.
Possible solutions:
Prepare an interface with conversion method and use that method to convert XElement
to your class instances:
public interface IXEntity<T>
{
T GetEntity(XElement source);
}
public IQueryable<T> GetAll<T>(IXEntityFactory<T> factory)
{
XElement xml = XElement.Load(this.url);
var nodes = xml.Elements().Select(xe => factory.GetEntity(xe));
return nodes.AsQueryable();
}
or extend your method to get conversion delegate:
public IQueryable<T> GetAll<T>(Func<XElement, T> projection)
{
XElement xml = XElement.Load(this.url);
var nodes = xml.Elements().Select(xe => projection(xe));
return nodes.AsQueryable();
}
btw. I have no idea why you're trying to use IQueryable<T>
. LINQ to XML uses IEnumerable<T>
anyway, so there is no difference between version with AsEnumerable()
and without that call.
Upvotes: 1
Reputation: 564641
You're trying to cast the XElement
to T
, not it's Value. You should be able to use:
public IQueryable<T> GetAll() where T : IConvertible
{
XElement xml = XElement.Load(this.url);
var nodes = xml.Nodes().Select(xe => Convert.ChangeType(xe.Value, typeof(T))).Cast<T>();
return nodes.AsQueryable();
}
This works by extracting the value as a string, and using Convert to (attempt) to map it to the specified type. This would require the type T
to implement IConvertible
, so I also added that constraint.
Upvotes: 1