Using LINQ expression to assign to an object's property - c#

So I'm working with an old data model, and I kind of have to work within what I've been handed.
When I perform a database query, the model returns data as a
List<Dictionary<string, object>>
Where for each dictionary, the key is the column name and the value is the column value. As you can imagine, working with this is a nightmare of foreach loops and type casting
I'm hoping to define some POCO viewmodels and then making something that uses LINQ/reflection, and an "assignment binding map" to go from hideous return value to my nice clean POCO. So I could define "maps" with the column names and lambdas to the properties on my POCO, similar to this...
var Map; // type???
Map.Add("Id", p => p.Id);
Map.Add("Code", p => p.Code);
Map.Add("Description", p => p.Description);
Map.Add("Active", p => p.Active);
Then convert like this...
List<Dictionary<string, object>> Results = MyModel.Query(...);
List<ProductViewModel> POCOs = new List<ProductViewModel>();
foreach (var Result in Results) // Foreach row
{
ProductViewModel POCO = new ProductViewModel();
foreach (var i in Result) // Foreach column in this row
{
// This is where I need help.
// i.Key is the string name of my column.
// I can get the lambda for this property from my map using this column name.
// For example, need to assign to POCO.Id using the lambda expression p => p.Id
// Or, assign to POCO.Code using the lambda expression p => p.Code
}
POCOs.Add(POCO);
}
return POCOs;
Can this be done using some sort of reflection, and if so, how?

Here is an approach using expression trees. First, define the API of the map:
public class PropertyMap<T> where T : new()
{
public void Add(string sourceName, Expression<Func<T, object>> getProperty);
public T CreateObject(IDictionary<string, object> values);
}
You would use it like this:
var map = new PropertyMap<ProductViewModel>();
map.Add("Id", p => p.Id);
map.Add("Code", p => p.Code);
map.Add("Description", p => p.Description);
map.Add("Active", p => p.Active);
var productViewModel = map.CreateObject(values);
To implement it, first you would declare a dictionary to associate names from the data source to properties:
private readonly IDictionary<string, PropertyInfo> _properties = new Dictionary<string, PropertyInfo>();
Next, you would implement the Add method in terms of that dictionary (all error handling left as an exercise for the reader):
public void Add(string sourceName, Expression<Func<T, object>> getProperty)
{
_properties[sourceName] = (PropertyInfo) ((MemberExpression) getProperty.Body).Member;
}
Then, you would dynamically compile a method, using expression trees, which does the assignments (it sounds scarier than it is). The easiest way to visualize this process is to look at an example of what we're building. What we want is some code which does this:
new ProductViewModel
{
Id = ...,
Code = ...,
Description = ...,
Active = ...
}
But, we can't know that at compile-time because of the dynamic mappings. So, we'll build a function which is that exact code, but compiled at runtime. Expression trees are just runtime data that represents the same code you could write at compile-time.
First, we need to get a set of bindings (assignments) for the properties:
private IEnumerable<MemberBinding> GetPropertyBindings(IDictionary<string, object> values)
{
return
from sourceName in _properties.Keys
select Expression.Bind(_properties[sourceName], Expression.Constant(values[sourceName]));
}
What we're saying here is, for each property in the mapped properties, look up the value and make it a constant (for Id, this might be the value 7) and bind the corresponding property to it. This gives us the expression Id = 7. We repeat this for all of the properties, giving us all of the assignments.
Once we have those bindings, we can create the full member initialization, which includes the constructor call:
private MemberInitExpression GetMemberInit(IDictionary<string, object> values)
{
return Expression.MemberInit(Expression.New(typeof(T)), GetPropertyBindings(values));
}
Because we specified where T : new() in the class declaration, we are guaranteed to have a parameterless constructor to call here. We pass in the property bindings we created before, giving us a data structure that represents the initialization expression we wanted to build.
So what do we do know? We have this data structure, but how do we call the code? To do that, we have to wrap that expression in a function that we can call, because the only thing you can actually invoke is a method. This means we are really building code that looks like this:
() => new ProductViewModel
{
Id = ...,
Code = ...,
Description = ...,
Active = ...
}
That is a parameterless function which, when invoked, will return the initialized object. This is also called a lambda expression. We can get the data structure for this like so:
private Func<T> GetInitializationFunction(IDictionary<string, object> values)
{
var initializationLambda = Expression.Lambda<Func<T>>(GetMemberInit(values));
return initializationLambda.Compile();
}
We create a lambda expression whose body is the member initialization, which is exactly the code we wrote above. We specify the delegate type Func<T> because it takes no parameters and returns an object of the mapped type.
Then, we compile it. This call generates a method with the signature Func<T> that we can call, and which has as its body the code we created as a data structure. This is a neat way of doing reflection without using reflection directly.
Finally, we implement the CreateObject method we defined earlier by creating the function and invoking it, giving us an instance of T (ProductViewModel here):
public T CreateObject(IDictionary<string, object> values)
{
var initializationFunction = GetInitializationFunction(values);
return initializationFunction();
}

What you could do is to extract the property name from a linq expression of the kind p => p.Id using something like this
public static string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
..and then use plain old reflection to actually assign the value to the object instance. For instance create a method
private void Assign(object objInstance, Expression<Func<T>> propertyExpression, object value)
{
string propertyNameToAssign = GetPropertyName(propertyExpression);
//TODO use reflection to assign "value" to the property "propertyNameToAssign" of "objInstance"
}
(didn't compile the code; for the reflection part, there are numerous articles on the web. Hope this helps)

This seems like a perfect match for dynamic . You can create a dynamic class that has the properties based on the keys in the dictionary. Check the DynamicObject class.

Related

How to simulate method overloading based on generic return type in c#

I have a read model as IQueryable<CustomType>, I use this inside my Web application. A lot of time I need to extract from this read model different View Model.
I use to write extension method like:
public static ViewModelA AsViewModelA(this IQueryable<CustomType> query)
{
var vm = view
.Select(x => new ViewModelA
{
Something = x.Something
}).FirstOrDefault();
return vm;
}
public static ViewModelB AsViewModelB(this IQueryable<CustomType> query)
{
var vm = view
.Select(x => new ViewModelB
{
SomethingElse = x.SomethingElse
}).FirstOrDefault();
return vm;
}
This do the job but I don't like the mess generated with method names; a more generic way, something like this would be preferable:
query.AsViewModel<ViewModelA>()
I know that return type is not intended as method signature (so no overload applies) and I know that generic type is not sufficient to make an overload.
What I would is a mechanism to just simulate overloading based on generic type. This mechanism should avoid a main method with cascading if/then/else. There is a way? Maybe with dynamics?
One option is to have a map from the type to a conversion of CustomType to that type. So it would look something like:
private static readonly Dictionary<Type, Expression> Mappings =
new Dictionary<Type, Expression>
{
{ typeof(ViewModelA),
Helper<ViewModelA>(x => new ViewModelA { Something = x.Something }) },
{ typeof(ViewModelB),
Helper<ViewModelB>(x => new ViewModelB { SomethingElse = x.SomethingElse }) },
...
}
// This method just helps avoid casting all over the place.
// In C# 6 you could use an expression-bodied member - or add a
private static Expression<Func<CustomType, T>> Helper<T>
(Expression<Func<CustomType, T>> expression)
{
return expression;
}
public static T AsViewModel<T>(this IQueryable<CustomType> query)
{
Expression rawMapping;
if (!Mappings.TryGetValue(typeof(T), out rawMapping))
{
throw new InvalidOperationException("Or another exception...");
}
// This will always be valid if we've set up the dictionary properly
var mapping = (Expression<Func<CustomType, T>>) rawMapping;
return view.Select(mapping).FirstOrDefault();
}
You can make the dictionary construction a bit cleaner with a bit more up-front code.
Well, yes, you can use dynamic:
private static ViewModelA AsViewModelInternal(this IQueryable<CustomType> query,
ViewModelA dummy) { ... }
private static ViewModelB AsViewModelInternal(this IQueryable<CustomType> query,
ViewModelB dummy) { ... }
public static T AsViewModel<T>(this IQueryable<CustomType> query)
{
return (T)query.AsViewModelInternal(default(T));
}
Make sure to handle a non-existing overload, of course :) The easiest way is to add an overload that takes object as the last argument, so that you basically have a "fallback overload".
However, I wouldn't recommend that. One of the great benefits of generics is you get great compile-time checks. This generic method pretends to accept all possible T's, but it actually doesn't. It's the equivalent of taking object instead of ViewModelA/ViewModelB.
It's not like there's a world's difference between
query.AsViewModelB()
and
query.AsViewModel<ViewModelB>()
I'd only use the alternative if you often find yourself having to use a generic type argument when calling AsViewModel, i.e. when you don¨t know the specific 'type in advance.

How would I get all public properties of object faster than with PropertyInfo.GetValue()?

I have the following generic code that iterates over IEnumerable<T> (assuming all objects are exactly of type T) and for each item it retrieves all properties values and appends them to a StringBuilder:
Type t = typeof(T);
var properties = t.GetProperties();
foreach (var item in list)
{
foreach (var property in properties)
{
object value = property.GetValue(item, null);
// feed to StringBuilder
}
}
and btw the IEnumerable comes from a non-trivial Linq-To-Sql query.
So I profile my code and find that of all my code 37,3% time is spent in System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader.MoveNext() and 31,59% time is spent in RuntimePropertyInfo.GetValue().
This is why I'd be happy to find another way of retrieving all properties - one that is faster than calling PropertyInfo.GetValue().
How could I achieve that (preferable keeping the code generic)?
The strategy is to cache a delegate that is not attached to any instance of a particular object. This is a little trickier than it sounds.
Jon Skeet's article on the topic is good for the general case, however I thought I'd offer a simplified solution for this specific case.
The workhorse is Delegate.CreateDelegate which takes a MethodInfo and returns a delegate that takes the instance as a parameter. The MethodInfo is provided by PropertyInfo.GetGetMethod. The trick is that we want all the delegates to return an object but we can't simply use Func<T, object> as the delegate type. That type is not going to be compatible without a boxing instruction for value types.
To do that we leverage a helper method (below it is called CreateDelegateInternal) which we will invoke by reflection with the correct run-time types. Since we only call this once when loading the delegates, it is not too costly. Then we will wrap the strongly-typed delegate in a less strongly typed lambda which will insert the correct conversion.
public static class ReflectionHelper<T>
{
private static readonly IEnumerable<Func<T, object>> propertyDelegates = CreateDelegates().ToArray();
private static IEnumerable<Func<T, object>> CreateDelegates()
{
var helper = typeof(ReflectionHelper<T>).GetMethod("CreateDelegateInternal", BindingFlags.Static | BindingFlags.NonPublic);
var properties = typeof(T).GetProperties();
foreach(var property in properties)
{
var method = helper.MakeGenericMethod(typeof(T), property.PropertyType);
yield return (Func<T, object>)method.Invoke(null, new object[] { property.GetGetMethod() });
}
}
private static Func<T, object> CreateDelegateInternal<T, TReturn>(MethodInfo m)
{
var f = (Func<T, TReturn>)Delegate.CreateDelegate(typeof(Func<T, TReturn>), m);
return t => (object)f(t);
}
public static IEnumerable<Func<T, object>> Properties
{
get { return propertyDelegates; }
}
}
and your code would look something like:
foreach (var item in list)
{
foreach (var property in ReflectionHelper<T>.Properties)
{
object value = property(item);
// feed to StringBuilder
}
}
Obviously, you may want may add some validation (to check the property's CanRead property) and error handling. Also, you may want to tuple up the PropertyInfo in the output so you could print metadata like names, this is left simple for clarity.

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

Using reflection to address a Linqed property

I'm trying to writing a generic method that will load a record of a specific type, with a specific ID. Here's one way that works:
public abstract class LinqedTable<T> where T : LinqableTable {
public static T Get(long ID) {
DataContext context = LinqUtils.GetDataContext<T>();
var q = from obj in context.GetTable<T>()
where obj.ID == ID
select obj;
return q.Single<T>();
}
}
public abstract class LinqableTable {
public abstract long ID { get; set; }
}
You can ignore the call to LinqUtils.GetDataContext<T>(); that's a utility function I've got to deal with the fact that I have multiple data contexts in my program. The point is that now I can declare any of my classes as subclasses of LinqableTable, and I can easily instantiate a record of that table just by calling LinqedTable<MyType>.Get(ID).
This has some limitations, however. Firstly, it forces all of my tables to have an I
identity field of type long, named ID. Secondly, because I'm using an abstract method, I am forced to go to the O/R designer and change the inheritance property of every ID field in my system to "override".
I want more flexibility than that. So naturally, I tried reflection, and came out with the following:
public abstract class LinqedTable<T> where T : LinqableTable {
public static T Get(long ID) {
DataContext context = LinqUtils.GetDataContext<T>();
var q = from obj in context.GetTable<T>()
where obj.IDValue == ID
select obj;
return q.Single<T>();
}
}
public abstract class LinqableTable {
internal long IDValue {
get { return (long)IDProperty.GetValue(this, null); }
set { IDProperty.SetValue(this, value, null); }
}
internal PropertyInfo IDProperty {
get { return this.GetType().GetProperty(IDPropertyName); }
}
internal protected virtual string IDPropertyName {
get { return "ID"; }
}
}
Theoretically, this allows me to override the ID column name, the cast to long should be OK with any integral data type, and I don't need to go defining all my ID columns as overrides.
BUT
Linq doesn't like this. On the call to q.Single<T>(); I get a runtime error:
The member 'EISS.Utils.LinqableTable.IDValue' has no supported translation to SQL.
OK, today I learned that Linq does some kind of magic on the back end; it doesn't instantiate obj and just read the IDValue property. So must be there's some attribute that needs to be set on the IDValue property that lets Linq do its thing.
But what?
Linq to SQL tries to translate your linq-query into SQL, but it does not know how to translate your property to a column name in the DB.
A good explanation can be found here on SO:
simple linq to sql has no supported translation to SQL
But how to solve it, is another matter. I have with succes used the apporoach from this thread:
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/df9dba6e-4615-478d-9d8a-9fd80c941ea2/
Or you can use dynamic query as mentioned here by scott guthrie:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Having read these posts: Generic Data Access using LINQ to SQL and C#,
LINQ-to-SQL: Generic Primary Key function and
Calling a generic method with Type
My colleague and I came up with the following digest:
We added the following method to our datacontext (in a partial class).
public T GetInstanceByPrimaryKey<T>(object primaryKeyValue) where T : class
{
var table = this.GetTable<T>();
var mapping = this.Mapping.GetTable(typeof(T));
var pkfield = mapping.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
if (pkfield == null)
throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
var param = Expression.Parameter(typeof(T), "e");
var predicate =
Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(param, pkfield.Name), Expression.Constant(primaryKeyValue)), param);
return table.SingleOrDefault(predicate);
}
Then, where we need to instanciate from the type name and primary key value:
string name = "LinqObjectName";
int primaryKey = 123;
var dc = new YourDataContext();
Type dcType = dc.GetType();
Type type = dcType.Assembly.GetType(String.Format("{0}.{1}", dcType.Namespace, name));
MethodInfo methodInfoOfMethodToExcute = dc.GetType().GetMethod("GetInstanceByPrimaryKey");
MethodInfo methodInfoOfTypeToGet = methodInfoOfMethodToExcute.MakeGenericMethod(name);
var instance = methodInfoOfTypeToGet.Invoke(dc, new object[] { primaryKey });
return instance;
Hope this helps!
Since LINQ statements referred to a LINQ-to-SQL IQueryable are translated to SQL queries, you will have to use the AsEnumerable extension (which will in turn cause a read of all the items in the database) and do reflection-related stuff on that IEnumerable.
EDIT
As required here's a clarificationAs specified in a comment, what I meant was something like:
(from obj in context.GetTable<T>() select obj).AsEnumerable().Where(x => x.IDValue == ID)
Unlike a query executed on an IQueryable, which can be perfectly translated to SQL such as
context.GetTable().Where(x => x.Text == "Hello")
which gets converted to something similar to
SELECT * FROM TABLE_MAPPED_TO_TYPE_T WHERE Text = 'Hello'
a query executed against an IEnumerable - in your case - will be executed by fetching all the entries of your table and then applying code-wise the specified filter.

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