Completely rewriting this question since I understand more now than I did before.
I am attempting to abstract out the conversion of an OData query string directly to .NET expression tree. There appear to be a number of questions and articles on this, but no answers that provide an abstract solution that relies soley on the Microsoft.Data.OData
namespace (ie, all examples rely on WebAPI, Entity Framework, or some other library).
The answer that does the best at providing an abstract solution is here:
https://mcmap.net/q/686777/-how-to-parse-odata-filter-with-regular-expression-in-c
These two lines got me started:
IEdmModel model = EdmxReader.Parse(new XmlTextReader(/*stream of your $metadata file*/));
IEdmEntityType type = model.FindType("organisation");
After much toil, I've learned that OData requires an EDM in order to generate its own proprietary expression tree model. It's only a model. You have to traverse that model to ultimately generate your own expression tree.
So I've done all of this (sort of). I happened upon this article which showed me how to create a basic EDM without any navigation:
Using that, I ended up creating an EDM generator that recursively reflects through a class to build the EDM. The problem is that this is ridiculously complex and there isn't much information online about how to create an EDM dynamically, so it doesn't define any navigation properties and only works with a single entity.
I then created an ODataExpressionVisitor that's modeled after System.Linq.Expressions.ExpressionVisitor
. It works pretty good. It's able to take this OData query string:
var filter = ODataUriParser.ParseFilter(
"(Name eq 'Oxford Mall' or Street eq '123 whatever ln') and Id eq 2",
edmBuilder.Model, edmBuilder.Model.FindType(typeof(CustomerLocation).FullName));
And generate this expression:
(
$CustomerLocation.Name == "Oxford Mall" ||
$CustomerLocation.Street == "123 whatever ln"
) &&
$CustomerLocation.Id == 2
It works, too, because I can compile it to a delagate and pass a CustomerLocation
object into it and it will return the proper true/false. I haven't tested it with EF6 or my other expression-based framework yet, though.
However, I think I am recreating a wheel here. There must be an existing means to 1) generate an convention-based EDM from a class alone and 2) convert the resulting OData expression tree to a .NET expression tree.