How to combine MemberExpression instances in C# for a LambdaExpression? - c#

Given a class like this:
public class AnEntity
{
public int prop1 { get; set; }
public string prop2 { get; set; }
public string prop3 { get; set; }
}
I am able to generate a lambda expression that selects one property like this:
ParameterExpression pe = Expression.Parameter(typeof(AnEntity), "x");
MemberExpression selectClause = Expression
.MakeMemberExpression(
pe,
typeof(AnEntity).GetProperty(prop2)); // selecting prop2
var selectLambda = Expression.Lambda<Func<AnEntity, object>>(selectClause, pe);
I can then use the lambda expression like this:
IQueryable<AnEntity> myEntities = dbContext.MyEntities.AsQueryable();
var results = myEntities.Select(selectLambda);
How can I add a second select clause to the selectLambda? For example, how would I select both prop2 and prop3?

Below is a fleshed out example of what "usr" described in his solution using MemberInitExpression.
For my solution, I am going to provide you with a new class that you will want write the expression result into. In reality, this could be the POCO for the entity itself, but by specifying a different class, it is clearer which class is the class you are projecting into as compared to the class you are projecting from. As "usr" mentioned, you can also try to use Tuple or other constructs. My current favorite is to use the extra code I appended to the bottom to create a new type dynamically. This is a bit more flexible than Tuple, but it has some disadvantages in that it requires Reflection to access it for the most part.
Class to project into:
public class Holder
{
public int Item1{ get; set; }
public string Item2 { get; set; }
public string Item3 { get; set; }
}
Code to create expression:
ParameterExpression paramExp = Expression.Parameter(typeof(AnEntity));
NewExpression newHolder = Expression.New(typeof(Holder));
Type anonType = typeof(Holder);
MemberInfo item1Member = anonType.GetMember("Item1")[0];
MemberInfo item2Member = anonType.GetMember("Item2")[0];
MemberInfo item3Member = anonType.GetMember("Item3")[0];
// Create a MemberBinding object for each member
// that you want to initialize.
MemberBinding item1MemberBinding =
Expression.Bind(
item1Member,
Expression.PropertyOrField(paramExp, "prop1"));
MemberBinding item2MemberBinding =
Expression.Bind(
item2Member,
Expression.PropertyOrField(paramExp, "prop2"));
MemberBinding item3MemberBinding =
Expression.Bind(
item3Member,
Expression.PropertyOrField(paramExp, "prop3"));
// Create a MemberInitExpression that represents initializing
// two members of the 'Animal' class.
MemberInitExpression memberInitExpression =
Expression.MemberInit(
newHolder,
item1MemberBinding,
item2MemberBinding,
item3MemberBinding);
var lambda = Expression.Lambda<Func<AnEntity, Holder>>(memberInitExpression, paramExp);
Finally, how you would call the expression:
IQueryable<AnEntity> myEntities = dbContext.MyEntities.AsQueryable();
var results = myEntities.Select(selectLambda);
Here is some additional code if you wanted to define a type dynamically for the return value:
public static Type CreateNewType(string assemblyName, string typeName, params Type[] types)
{
// Let's start by creating a new assembly
AssemblyName dynamicAssemblyName = new AssemblyName(assemblyName);
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule(assemblyName);
// Now let's build a new type
TypeBuilder dynamicAnonymousType = dynamicModule.DefineType(typeName, TypeAttributes.Public);
// Let's add some fields to the type.
int itemNo = 1;
foreach (Type type in types)
{
dynamicAnonymousType.DefineField("Item" + itemNo++, type, FieldAttributes.Public);
}
// Return the type to the caller
return dynamicAnonymousType.CreateType();
}

The way to answer questions like these is to write the pattern you want to build in strongly typed C# (select new { x.p1, x.p2 }) and use the debugger to look at the expression tree. Then you build that tree yourself.
What you will find is a MemberInitExpression instantiating a class with the two properties p1 and p2 that are being initialized from x.
You have to supply such a class somehow. Either define it yourself (class X { string p1, p2; }) or use a Tuple-like construct. Or an object[].
Understand that you can only have one return value. So it needs to encapsulate multiple values.
The easiest way is going to be using an object[]. Look at how the C# compiler does it.

There is no "second select return value". You get to return one value, which might be an aggregate.
The C# language provides a lot of syntactic sugar in this area, in the form of LINQ and anonymous types. To return an aggregate via a lambda built by expression trees, you'll have to create a type to hold all the different values (just like the C# compiler does behind the scenes when it sees an anonymous type) and then call its constructor passing the multiple values you want to return (this is actually somewhat easier than what C# does behind the scenes, which is call a bunch of property setters). At runtime, there are no anonymous types. They all get named, if not by the programmer then by the compiler.
In fact you can probably use a Tuple<Type1, Type2, Type3> instead of making a class especially for the purpose. But then your member properties won't be named nicely.

Related

Expression Tree: Get property value of dynamic object

I have list of dynamic objects where I want to query by custom property. In other words, it would look like this if I wasn't going for reflection:
IEnumerable<User> FilterUsers(IEnumerable<User> users, string selectedValue)
{
users.Where(user => user.Name == selectedValue);
}
So far I've come up with the following implementation that works if users is typed:
IEnumerable<User> FilterUsers(IEnumerable<User> users, string selectedField, string selectedValue)
{
LabelTarget returnTarget = Expression.Label(typeof(bool));
ParameterExpression userParameter = Expression.Parameter(typeof(User));
MemberExpression userSelectedField = Expression.Property(userParameter, selectedField);
Expression test = Expression.Equal(userSelectedField, Expression.Constant(selectedValue));
Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));
var ex = Expression.Block(
Expression.IfThenElse(test, iftrue, iffalse),
Expression.Label(returnTarget, Expression.Constant(false)));
var whereClause = Expression.Lambda<Func<User, bool>>(
ex,
new ParameterExpression[] { userParameter }
).Compile();
return users.Where(user => whereClause(user));
}
What I am really trying to do is to make users dynamic object:
IEnumerable<dynamic> FilterUsers(IEnumerable<dynamic> users, string selectedField, string selectedValue) {
// ...
ParameterExpression userParameter = Expression.Parameter(typeof(object)); // ???
MemberExpression userSelectedField = Expression.Property(userParameter, selectedField); // throws
// ...
}
This throws the following exception: Instance property 'Name' is not defined for type 'System.Object' (Parameter 'propertyName'). What am I missing?
Alternatively, how can I use Dictionary<string, object>?
Using dynamic here doesn't get you much: you'd be better off using generics if you can:
IEnumerable<T> FilterUsers<T>(IEnumerable<T> users, string selectedField, string selectedValue)
{
var userParameter = Expression.Parameter(typeof(T));
var userSelectedField = Expression.Property(userParameter, selectedField);
// etc...
}
If you do need to use dynamic, then you'll need to get the runtime type of each user, using .GetType(). However bear in mind that there's nothing stopping someone from passing in an IEnumerable containing lots of different types of object, and they don't all have to have a property called selectedField!
Or, they might pass in lots of different types of object, each of one has a property called selectedField, but they're distinct properties (e.g. class A { public string Foo { get; set; } } and class B { public string Foo { get; set; } } -- those two Foo properties are distinct).
So you'll have to call .GetType() on each one of them, which means you won't be able to get the performance benefits of using compiled expressions.
If you can guarantee that all elements have the same type, you can do something like:
private static IEnumerable<dynamic> FilterCollection(IEnumerable<dynamic> collection, string property, string value)
{
if (!collection.Any()) return collection;
var collectionItemType = collection.First().GetType();
var userParameter = Expression.Parameter(typeof(object));
var convertedUser = Expression.Convert(userParameter, collectionItemType);
var userSelectedField = Expression.Property(convertedUser, selectedField);
...
}
Beware however that you're enumerating users twice, which is probably a bad thing. You might do better to get the IEnumerator yourself and work with it explicitly.
As #canton7 said you should be using a generic method. I also see in your question you specified you're looking for properties, why not use regular old reflection?
public static IEnumerable<T> FilterItems<T>(IEnumerable<T> items, string property, string value)
{
var prop = typeof(T).GetProperties().First(p => p.Name == property);
return items.Where(i => prop.GetValue(i).ToString().Contains(value));
}
Of course that code should be enhanced to handle different errors....

How do you create an Expression of an enum from its type and the name of one of its fields?

Had a hard time finding what I'm trying to do and this post was the closest I could find. This post won't work as I don't know the integer value of the enum, I only know its name. Given the following code:
public enum Foo
{
Row = 0,
Column = 20, // This is why the second post won't work, I only know the name "Column"
None = 30
}
public static class ExpressionGetter
{
public static Expression GetExpression(Type type, string name)
{
// Not sure what I should do here. I want an expression object for Foo.Row
}
}
void Main()
{
var expression = ExpressGetter.GetExpression(typeof(Foo), "Row");
}
Later in my application, I am building expression trees to generate LINQ queries and I know the type of the enum and name of the enum and now I want to create an Expression.Constant of it or if there's another way to do this, I'd like to know how.
I want at the end an expression that looks like this:
Foo.Row
I've tried:
Expression.Property(null, enumType, name)
But it does not work. Results in
ArgumentException: Property 'Row' is not defined for type 'Foo'
Parameter name: propertyName
which makes sense because it's a struct not an object.
So I'm not sure how to build the Expression Foo.Row given the enum type Foo and the name as a string.
An enum value is a static field of the enum type. If you only have the name of the enum value as a string, the second version is what you're looking for. But you could also do Enum.Parse() with the first version.
Expression.Constant(Foo.Row, typeof(Foo));
// Or any other string that's valid
var name = "Row";
MemberExpression.Field(null, typeof(Foo), name);
More or less like this:
public enum EnumerationTest
{
A, B, C
}
public class ClassTest
{
public EnumerationTest Test { get; set; }
}
public static Expression PropertyExpression()
{
// Think of this like a lambda (p) => p.Test == Enumeration.A
var parameter = Expression.Parameter(typeof(ClassTest), "p");
var property = Expression.PropertyOrField(parameter, "Test");
var value = (EnumerationTest)Enum.Parse(typeof(EnumerationTest), "A");
var constant = Expression.Constant(value, typeof(EnumerationTest));
return Expression.Equal(property, constant);
}
You generally are using a lot of reflection and string parsing when doing Expression trees. At least that's what I have found in my experience

Generic function that takes properties as parameters

I want to write a generic function that takes an object and a series of properties of this object. Inside the function I would like to select a new anonymous object that is simply just those properties of the passed in object.
I want to do something like this:
public class SimpleClass
{
public DateTime ADate {get; set;}
public string StringHere {get; set;}
public int ANumber {get; set;}
}
var testObj = new SimpleClass();
// set values here on testObj properties
DoStuffHere(testObj, StringHere, ANumber);
I could pass in the properties as strings and then use reflection to get the properties from the passed in object, but I wanted to know if there was some way I could pass in the properties themselves so I could have intellisense and compile time checking to prevent bad property names. I would like my getNewClass function to take any type of object, and such, be generic.
Edit: I am not returning a new anonymous type. I think my function name was making it sound that way. I am going to be selecting a new anonymous type internally from a list of that specified testObj and generating a PDF from those properties.
Defining an anonymous type is actually very complicated, and trying to do it just with the names is somewhat challenging. Essentially what you want already exists, but in regular C# - so for a single object:
var obj = new { testObj.StringHere, testObj.ANumber };
Or for multiple objects:
var projection = from obj in sequence
select new { obj.StringHere, obj.ANumber };
That's about as succinct as you'll get. You could add a generic method that took a Func<,> of some kind, but it wouldn't be any cleaner than the above.
It isn't useful to have:
var obj = SomeMagicMethod(obj, "StringHere", "ANumber");
because SomeMagicMethod could only usefully return object - our obj variable would be largely unusable.
If you don't need to return the object from the method, then you could use either of:
SomeMagicMethod<T>(T value) {
...
}
...
SomeMagicMethod(new {testObj.StringHere, testObj.ANumber });
or:
SomeMagicMethod<TFrom, TTo>(TFrom value, Func<TFrom, TTo> selector)
{
TTo actualVal = selector(value);
...
}
...
SomeMagicMethod(testObj, x => new {x.StringHere, x.ANumber });
Personally, I think the first is easier - the func in the second is overkill.
You could also just use reflection...
SomeMagicMethod(object obj, params string[] names)
{
foreach(var name in names) {
object val = obj.GetType().GetProperty(name).GetValue(obj);
// ...
}
}
//...
SomeMagicMethod(testObj, "StringHere", "ANumber");
you can pass them as lambda:
GetNewClass (testObj, ()=>StringHere, ()=> ANumber);
and have a signature for GetNewClass like
void GetNewClass (object, Expression<Func<object>> expr0, Expression<Func<object>> expr1);
You can then get the property quite easily.
You can use Linq expressions for that.
(note: it's possible you need to modify a few things in the snippet below, this is of the top of my hat):
public void getNewClass(Object testObj, params MemberExpression Fields[])
{
foreach(MemberExpression field in Fields)
{
// Get the name
var name = field.Member.Name;
// get the value
var member= Expression.Convert(field, typeof(object));
var lambda= Expression.Lambda<Func<object>>(member);
var fnc= lambda.Compile();
var value = fnc();
}
}
This snippet show how to get the name of the property and the value. It can be called like this:
getClass(someObj, obj => obj.SomeProperty, obj.SomeOtherProperty);

Creating an expression from the string of a property name?

I am trying to create a query based on some JSON, I currently have the JSON parsed into a set of rules, each rule contains the name of the field, the type of comparison (=, > etc) and the value to compare.
The issue I am having is getting it from that rule, to an IQueryable object, I am guessing I need to use reflection and somehow build the expression tree, but I'm not sure on the right approach...
Assuming I have:
public class Order : BaseEntity
{
public int OrderID{ get; set; }
}
and I have the rule which is:
public class Rule
{
public string field { get; set; }
public Operations op { get; set; }
public string data { get; set; }
}
Running it I get:
field = "OrderID"
op = "eq"
data = "123"
I have the method to parse it with the signature:
public IQueryable<T> FilterObjectSet<T>(IQueryable<T> inputQuery) where T : class
As part of this method I want to do:
inputQuery = inputQuery.Where(o => propertyInfo.Name == rule1.data);
This doesn't work because it basically just generates the sql "OrderID" = "123" which is obviously wrong, I need it to take the column name from inputQuery that has the same name as propertyInfo.Name and build the query that way...
Hope that made sense? Any suggestions?
Edit: I guess what I am asking is to convert a string (Because I can build one pretty simply from the rule) to an expression, maybe using Dynamic LINQ?
Something like this:
public static IQueryable<T> FilterObjectSet<T>(IQueryable<T> inputQuery,
Rule rule) where T : class
{
var par = Expression.Parameter(typeof(T));
var prop = Expression.PropertyOrField(par, rule.field);
var propType = prop.Member.MemberType == System.Reflection.MemberTypes.Field ?
((FieldInfo)prop.Member).FieldType :
((PropertyInfo)prop.Member).PropertyType);
// I convert the data that is a string to the "correct" type here
object data2 = Convert.ChangeType(rule.data,
propType,
CultureInfo.InvariantCulture);
var eq = Expression.Equal(prop, Expression.Constant(data2));
var lambda = Expression.Lambda<Func<T, bool>>(eq, par);
return inputQuery.Where(lambda);
}
If you need some explanation, you can ask. Note that this won't work on types that have special implicit conversions (like a MyString type that has an implicit conversion from string). This because Convert.ChangeType uses only the IConvertible interface.
Null handling for data is perhaps something else that should be handled.
Be aware that I'm not sure the Expression.PropertyOrField is handled by the various IQueryable<T> engines (LINQ-to-SQL and EF). I have only tested it with the AsQueryable() engine. If they don't "accept" it, you must split it in a Expression.Property or Expression.Field depending on what rule.field is.
A nearly equivalent version that doesn't use Expression.PropertyOrField:
public static IQueryable<T> FilterObjectSet<T>(IQueryable<T> inputQuery,
Rule rule) where T : class
{
Type type = typeof(T);
var par = Expression.Parameter(type);
Type fieldPropertyType;
Expression fieldPropertyExpression;
FieldInfo fieldInfo = type.GetField(rule.field);
if (fieldInfo == null)
{
PropertyInfo propertyInfo = type.GetProperty(rule.field);
if (propertyInfo == null)
{
throw new Exception();
}
fieldPropertyType = propertyInfo.PropertyType;
fieldPropertyExpression = Expression.Property(par, propertyInfo);
}
else
{
fieldPropertyType = fieldInfo.FieldType;
fieldPropertyExpression = Expression.Field(par, fieldInfo);
}
object data2 = Convert.ChangeType(rule.data, fieldPropertyType);
var eq = Expression.Equal(fieldPropertyExpression,
Expression.Constant(data2));
var lambda = Expression.Lambda<Func<T, bool>>(eq, par);
return inputQuery.Where(lambda);
}
In the end I used a Dynamic Linq library I found on Guthrie's Blog:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Using this I was able to properly parse out and use the parameters I had built into the rules

How to create LINQ Expression Tree to select an anonymous type

I would like to generate the following select statement dynamically using expression trees:
var v = from c in Countries
where c.City == "London"
select new {c.Name, c.Population};
I have worked out how to generate
var v = from c in Countries
where c.City == "London"
select new {c.Name};
but I cannot seem to find a constructor/overload that will let me specify multiple properties in my select lambda.
This can be done, as mentioned, with the help of Reflection Emit and a helper class I've included below. The code below is a work in progress, so take it for what it's worth... 'it works on my box'. The SelectDynamic method class should be tossed in a static extension method class.
As expected, you won't get any Intellisense since the type isn't created until runtime. Works good on late-bound data controls.
public static IQueryable SelectDynamic(this IQueryable source, IEnumerable<string> fieldNames)
{
Dictionary<string, PropertyInfo> sourceProperties = fieldNames.ToDictionary(name => name, name => source.ElementType.GetProperty(name));
Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicType(sourceProperties.Values);
ParameterExpression sourceItem = Expression.Parameter(source.ElementType, "t");
IEnumerable<MemberBinding> bindings = dynamicType.GetFields().Select(p => Expression.Bind(p, Expression.Property(sourceItem, sourceProperties[p.Name]))).OfType<MemberBinding>();
Expression selector = Expression.Lambda(Expression.MemberInit(
Expression.New(dynamicType.GetConstructor(Type.EmptyTypes)), bindings), sourceItem);
return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), "Select", new Type[] { source.ElementType, dynamicType },
Expression.Constant(source), selector));
}
public static class LinqRuntimeTypeBuilder
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static AssemblyName assemblyName = new AssemblyName() { Name = "DynamicLinqTypes" };
private static ModuleBuilder moduleBuilder = null;
private static Dictionary<string, Type> builtTypes = new Dictionary<string, Type>();
static LinqRuntimeTypeBuilder()
{
moduleBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run).DefineDynamicModule(assemblyName.Name);
}
private static string GetTypeKey(Dictionary<string, Type> fields)
{
//TODO: optimize the type caching -- if fields are simply reordered, that doesn't mean that they're actually different types, so this needs to be smarter
string key = string.Empty;
foreach (var field in fields)
key += field.Key + ";" + field.Value.Name + ";";
return key;
}
public static Type GetDynamicType(Dictionary<string, Type> fields)
{
if (null == fields)
throw new ArgumentNullException("fields");
if (0 == fields.Count)
throw new ArgumentOutOfRangeException("fields", "fields must have at least 1 field definition");
try
{
Monitor.Enter(builtTypes);
string className = GetTypeKey(fields);
if (builtTypes.ContainsKey(className))
return builtTypes[className];
TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable);
foreach (var field in fields)
typeBuilder.DefineField(field.Key, field.Value, FieldAttributes.Public);
builtTypes[className] = typeBuilder.CreateType();
return builtTypes[className];
}
catch (Exception ex)
{
log.Error(ex);
}
finally
{
Monitor.Exit(builtTypes);
}
return null;
}
private static string GetTypeKey(IEnumerable<PropertyInfo> fields)
{
return GetTypeKey(fields.ToDictionary(f => f.Name, f => f.PropertyType));
}
public static Type GetDynamicType(IEnumerable<PropertyInfo> fields)
{
return GetDynamicType(fields.ToDictionary(f => f.Name, f => f.PropertyType));
}
}
The accepted answer is very useful, but I needed something a little closer to a real anonymous type.
A real anonymous type has read-only properties, a constructor for filling in all of the values, an implementation of Equals/GetHashCode for comparing the values of each property, and an implementation ToString that includes the name/value of each property. (See https://msdn.microsoft.com/en-us/library/bb397696.aspx for a full description of anonymous types.)
Based on that definition of anonymous classes, I put a class that generates dynamic anonymous types on github at https://github.com/dotlattice/LatticeUtils/blob/master/LatticeUtils/AnonymousTypeUtils.cs. The project also contains some unit tests to make sure the fake anonymous types behave like real ones.
Here's a very basic example of how to use it:
AnonymousTypeUtils.CreateObject(new Dictionary<string, object>
{
{ "a", 1 },
{ "b", 2 }
});
Also, another note: I found that when using a dynamic anonymous type with Entity Framework, the constructor must be called with the "members" parameter set. For example:
Expression.New(
constructor: anonymousType.GetConstructors().Single(),
arguments: propertyExpressions,
members: anonymousType.GetProperties().Cast<MemberInfo>().ToArray()
);
If you used one of the versions of Expression.New that does not include the "members" parameter, Entity Framework would not recognize it as the constructor of an anonymous type. So I assume that means a real anonymous type's constructor expression would include that "members" information.
Maybe a bit late but may help to someone.
You Can generate dynamic select by call DynamicSelectGenerator in select from an entity.
public static Func<T, T> DynamicSelectGenerator<T>()
{
// get Properties of the T
var fields = typeof(T).GetProperties().Select(propertyInfo => propertyInfo.Name).ToArray();
// input parameter "o"
var xParameter = Expression.Parameter(typeof(T), "o");
// new statement "new Data()"
var xNew = Expression.New(typeof(T));
// create initializers
var bindings = fields.Select(o => o.Trim())
.Select(o =>
{
// property "Field1"
var mi = typeof(T).GetProperty(o);
// original value "o.Field1"
var xOriginal = Expression.Property(xParameter, mi);
// set value "Field1 = o.Field1"
return Expression.Bind(mi, xOriginal);
}
);
// initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
var xInit = Expression.MemberInit(xNew, bindings);
// expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);
// compile to Func<Data, Data>
return lambda.Compile();
}
And use by this code:
var result = dbContextInstancs.EntityClass.Select(DynamicSelectGenerator<EntityClass>());
I don't believe that you will be able to achieve this. Although when you do select new { c.Name, c.Population } it seems like you're not creating a class you actually are. If you have a look at the compiled output in Reflector or the raw IL you will be able to see this.
You'll have a class which would look something like this:
[CompilerGenerated]
private class <>c__Class {
public string Name { get; set; }
public int Population { get; set; }
}
(Ok, I cleaned it up a touch, since a property is really just a get_Name() and set_Name(name) method set anyway)
What you're trying to do is proper dynamic class creation, something which wont be available until .NET 4.0 comes out (and even then I'm not really sure if it'll be able to achieve what you want).
You're best solution would be to define the different anonymous classes and then have some kind of logical check to determine which one to create, and to create it you can use the object System.Linq.Expressions.NewExpression.
But, it may be (in theory at least) possible to do it, if you're getting really hard-core about the underlying LINQ provider. If you are writing your own LINQ provider you can detect if the currently-parsed expression is a Select, then you determine the CompilerGenerated class, reflect for its constructor and create.
Defiantly not a simple task, but it would be how LINQ to SQL, LINQ to XML, etc all do it.
You could use the IQueryable-Extensions here, which is an implemantation of the solution described by "Ethan J. Brown":
https://github.com/thiscode/DynamicSelectExtensions
The Extension builds dynamically an anonymous type.
Then you can do this:
var YourDynamicListOfFields = new List<string>(
"field1",
"field2",
[...]
)
var query = query.SelectPartially(YourDynamicListOfFields);
You could use a parameter class instead of working with an anonymous type. In your example you can create a parameter class like this:
public struct ParamClass {
public string Name { get; set; };
public int Population { get; set; };
}
…and put it into your select like this:
var v = from c in Countries
where c.City == "London"
select new ParamClass {c.Name, c.Population};
What you get out is something of the type IQueryable<ParamClass>.
This compiles, I dunno if it works however...
myEnumerable.Select((p) => { return new { Name = p.Name, Description = p.Description }; });
Assuming p is what your transforming, and the select statement is returning an anon type, using the function declaration of lambda's.
Edit: I also don't know how you would generate this dynamically. But at least it shows you how to use the select lambda to return an anon type with multiple values
Edit2:
You would also have to bare in mind, that the c# compiler actually generates static classes of the anon type. So the anon type does actually have a type after compile time. So if your generating these queries at run time (which I assume you are) you may have to construct a type using the various reflection methods (I believe you can use them to make types on the fly) load the created types into execution context and use them in your generated output.
I think most of the things are already answered - as Slace said, you need some class that would be returned from the Select method. Once you have the class, you can use the System.Linq.Expressions.NewExpression method to create the expression.
If you really want to do this, you can generate class at runtime too. It's a bit more work, because it cannot be done using LINQ Expression trees, but it's possible. You can use System.Reflection.Emit namespace to do that - I just did a quick search and here is an article that explains this:
Introduction to Creating Dynamic Types with Reflection.Emit
You could use the Dynamic Expression API which allows you to dynamically build your select statement like this:
Select("new(<property1>,<property2>,...)");
You need the Dynamics.cs file from the LINQ and language samples for Visual Studio for this to work, both are linked at the bottom of this page. You can also see a working example showing this in action on at the same URL.

Categories

Resources