How to instantiate and initialize a dynamic object in expression tree? - c#

When working with IQuerayble<TItem> we can call Select like this:
query.Select( item => new { A=item.Prop1, B=item.Prop2});
And Select method expects Expression<Func<TItem,TResult>>
I need to use ExpandoObject instead of anonymous but statically typed class.
If it were possible it would look like:
query.Select( item => dynamic new ExpandoBoject { A=item.Prop1, B=item.Prop2});
So I want to construct expression tree Expression<Func<TItem,ExpandoObject>> where object's properties are initialized in the similar way as with anonymous type.
Dynamic functionality is only needed for initialization so it's ok that Func returns ExpandoObject instead of dynamic.
I cannot find much documentation about Expression.Dynamic and corresponding binders I should use.
Update 1
Why do I need all this stuff?
Because I want to get primary keys.
I want to do it for any entity type.
I know how to get the list of the properties composing PK, but now I need to make a tricky projection of the entity to EntityKey. Well, may be to same equvalent of this class.
var keys = context.Set<TEntity>().Where(Expression<Func<TEntity,bool>).Select(Expression<Func<TEntity,EntityKey>>);
As I noted in the comments lambdas containing blocks cannot be converted to expression trees so i cannot simple create the dictionary and fill it. Now I'm playing with the expression tree semantically close to this code:
var dict = new Dictionary<string,object>();
dict.Add("Prop1",value1);
dict.Add("Prop2",value2);
return dict
But I doubt EF can parse the expression containing blocks. Need to check.
And I'm curious whether it will work with dynamic objects and Expression.MemberInit as it works with static objects.
Update 2
Entity Framework does not support dictionary initialization syntax.
It throws NotSupportedException with the message: Only list initializer items with a single element are supported in LINQ to Entities.
Update 3
EF does not support block expressions aswell.
NotSupportedException with message: Unknown LINQ expression of type 'Block'.

Now I'm playing with the expression tree semantically close to this code:
var dict = new Dictionary<string,object>();
dict.Add("Prop1",value1);
dict.Add("Prop2",value2);
return dict;
You can do that, because you can write that code as as a single expression like this:
new Dictionary<string, object>
{
{ "Prop1", value1 },
{ "Prop2", value2 }
};
And you can create an expression tree that contains this expression (which EF should be able to handle) like this:
var addMethod = typeof(Dictionary<string, object>).GetMethod("Add");
var expression = Expression.Lambda<Func<Dictionary<string, object>>>(
Expression.ListInit(
Expression.New(typeof(Dictionary<string, object>)),
Expression.ElementInit(
addMethod,
Expression.Constant("Prop1"),
value1Expression),
Expression.ElementInit(
addMethod,
Expression.Constant("Prop2"),
value2Expression)),
itemParameterExpression);

The described thing is difficult mainly because we cannot create anonymous type dynamically at run time - they need to be known already at compile time. So my proposition is to create a class that may hold several properties of arbitrary chosen type (similar to Tuple), however we will load from db values only for properties important for us. So we need class like this:
public class CustomTuple<T1, T2>
{
public T1 Item1 { get; set; }
public T2 Item2 { get; set; }
}
We may add there more properties if we need more. If we would have such class with 5 properties that with use of it we may load at max 5 properties. Now the projection logic:
Type[] parameterTypes = new Type[] { typeof(int), typeof(object) };
Type tupleType = typeof(CustomTuple<,>).MakeGenericType(parameterTypes);
ParameterExpression x = Expression.Parameter(typeof(Entity));
NewExpression body = Expression.New(tupleType.GetConstructor(new Type[0]), new Expression[0]);
MemberBinding binding1 = Expression.Bind(
typeof(CustomTuple<,>).MakeGenericType(parameterTypes).GetProperty("Item1"),
Expression.Property(x, "Value"));
MemberInitExpression memberInitExpression =
Expression.MemberInit(
body,
binding1);
Expression<Func<Entity, object>> exp = Expression.Lambda<Func<Entity, object>>(memberInitExpression, x);
using (MyDbContext context = new MyDbContext())
{
var list = context.Entities.Select(exp).ToList();
}
The above code selects from Entities collection values of Entity class Value property. parameterTypes defines types of parameters returned from Select projection. If we do not intend to use given property then we leave it as of object type. Then we need to build initialization expression. We do this with method New, we assign the properties values with expression created by Expression.Bind and we combine them together with Expression.MemberInit. We may dynamically create at run time as much MemberBinding expressions as we need.

Related

Expression to get LINQ with Contains to EF for SQL IN() where on entities child's property equals value

I have a simple need to filter all parents out of the returned collection where there is no match on a field, that is called by name from a string, doesn't match a value presented. What I am after is if parent object has child object, and that child objects property "foo"(called by string) doesn't or does equal a value bar, the parent object is filtered from the collection appropriately.
Here is my linq ef call
var field = "bar";
var values = new List<string>{"foo","fuYu"};
var dataPage = _aim_context.ae_s_bld_c.AsNoTracking();
var result = dataPage.Where(x =>
DbHelper.byPropertyContains(x.udfs, field, values)
);
// NOTE `udfs` is a ONE-to-ONE with `ae_s_bld_c`
What I am looking to see is something like the SQL of
SELECT [m].[id],[m.udfs].[bar],
FROM [dbo].[ae_s_bld_c] AS [m]
INNER JOIN [dbo].[ae_s_bld_c_udf] AS [m.udfs]
ON ([m].[multitenant_id] = [m.udfs].[multitenant_id])
WHERE ([m].[multitenant_id] = 1.0)
AND ([m.udfs].[bar] IN ('foo','fuYu')) --< Goal line
The way I have approached this was to get an expression set up to take the List<string> and make the SQL. I have read near 50 articles and SO posts, but have not figured out exactly why I am not getting this just yet as everyone seems to have different ideas, and most are not in line with dotnet core 2.1+ it seems.
Here is what I am sitting at currently after many many iterations. NOTE: it is a little different from what I am after as I am giving my current trail.
My current context linq try
//...
dataPage = dataPage.Where(DbHelper.byPropertyContains<ae_s_bld_c>("udfs", field, values));
//...
I think it would be better if it was like the first example I put up, but that was what I have landed on since I have had a time lining it up with x=>x.udfs, both as x=> funName(x.udfs) and x=> x.udfs.funName()
My static method to build the expression
public static class DbHelper
{
public static Expression<Func<T, bool>> byPropertyContains<T>(string node, string field, List<string> value) {
//trying to take parent item and get it's property by string name because
// doing the function in linq like x=>x.udfs was not working right
// but that is the prefered I think
var property_parameter = Expression.Parameter(typeof(T), "x");
var property = Expression.PropertyOrField(property_parameter, node);
var selector_parameter = Expression.Parameter(property.Type, "y");
var selector = Expression.PropertyOrField(selector_parameter, field);
var methodInfo = typeof(List<string>).GetMethod("Contains", new Type[] {
typeof(string)
});
var list = Expression.Constant(value, typeof(List<string>));
var body = Expression.Call(methodInfo, list, selector);
return Expression.Lambda<Func<T, bool>>(body, selector_parameter);
}
}
Update
Per the request of #NetMage I have tried to work backwards with LINQpad. I think I am close but it is hard to tell with teh output. I am putting it up here for reference. To be clear, the property name of the child will be a string of the name. The best outcome is I could have a name like udfs.foo where I can test on any level if the values contain by string name, but really ok with it starting here,
var result = dataPage.Where(x =>
DbHelper.byPropertyContains(x.udfs, field, values)
);
Let start from here. You need an equivalent of something like this
var result = dataPage.Where(x => values.Contains(x.udfs.{field}));
where field is a string returning property dynamically specified by name.
In EF Core you don't even need to deal with building expresions by hand, because EF Core provides a special SQL translatable function for accessing simple properties by name called EF.Property.
With that method the solution is simple as that:
var result = dataPage
.Where(x => values.Contains(EF.Property<string>(x.udfs, field)));

C# Linq using variable for Model

Trying to write a piece of code that is dynamic in that it can accept any number of possible model definitions.
Current hard code is:
var items = _context.Events.ToList();
foreach (var item in items)
{
(...)
}
What I would like to do is to make the _context.Events.ToList(); be more like _context.{variable that holds model name}.ToList();
Something like:
var modelName = "Table1"
var items = _context.modelName.ToList();
foreach (var item in items)
{
(...)
}
I thought about declaring items as a generic variable, that way it was available to the entire method even if set inside an if or switch, but no idea on what to declare it as.
Is something like this possible?
Try this :
var table = (ITable)context.GetType()
.GetProperty(modelName)
.GetValue(context, null);
I hope be helpful :)
Entity Framework has a generic Set<TEntity> accessor, but the type must be known at compile-time:
var foo = _context.Set<Foo>();
If you have the type as a string variable, though, your options are extremely limited. You can technically use reflection to get at the right DbSet, but you're going to lose the generic IQueryable<TEntity> interface, and you'll be stuck with the much more limited IQueryable interface, and by "much more limited", I mean you basically can't do anything but materialize the set.
If you want to type it via a string variable, but still have at least some querying ability, you'll need to employ a base class that's shared between all the entity types you'd want to use in this way. For example, if you have different "event" types, and you can make them all inherit from Event, then you could do something like:
MethodInfo method = typeof(Queryable).GetMethod("OfType");
MethodInfo generic = method.MakeGenericMethod(new Type[] { eventType });
var set = (IQueryable<Event>)generic.Invoke(null, new object[] { _context.Events });
If your eventType was "Film", for example, that would effectively give you the same queryset as something like _context.Set<Film>() (where Film would be a derived class of Event). You could then utilize your normal LINQ query functionality like Where, Select, etc. on set.

Reflection: Setting properties of lots of objects using Dynamic Methods

So I have thousands of objects, of generic type T, and I want to cast them to an array of objects I got.
So I have to get the properties list T, and for each property set the value to the corresponding object on the array
for (int i = 0; reader.Read(); i++)
{
T tmp = (T)Activator.CreateInstance(typeof(T));
foreach (var prop in properties)
{
prop.SetValue(tmp, reader.GetValue(reader.GetOrdinal(prop.Name)), null);
}
}
reader is a DataReader. The problem I have is that prop.SetValue is sadly slow (consumes like 50% of the total excecution time), I've been told to use Dynamic Methods or Expression Trees, I tried using expression trees but from what I understood I have to generate one tree for each value I want to set, which wouldn't be so good.
So Dynamic Methods is the other option. Ideally I'd need to create a method SetProp(object, propertyName, value) which I can reuse over and over again.
Look at FastMember; either use it "as is", or steal all the code (DynamicMethod, etc). It does all this, with reflection-cache etc built in. Example usage:
var accessor = TypeAccessor.Create(typeof(T));
for (int i = 0; reader.Read(); i++)
{
T tmp = (T)Activator.CreateInstance(typeof(T));
foreach (var prop in properties)
{
accessor[tmp, propName] = newValue; // fill in name/value here
}
}
alternatively - use something like dapper-dot-net, that does that and handles all the materialization (since this is obviously data-access code).
I tried using expression trees but from what I understood I have to generate one tree for each value I want to set, which wouldn't be so good.
Why not? You'd basically build a List<Tuple<string, Action<object>>> by creating (and then compiling) an expression tree for each property in T. Then you iterate over the list and fetch the item for each property, then call the corresponding action.
I have a PropertyCopy class in MiscUtil which does something very similar - you may want to look at that for inspiration.
Alternatively, as of .NET 4 you could build a single Block expression tree which does all the property setting.
You can create a single expression tree for each property.
Just take the value as a parameter:
var instance = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(object));
var setter = Expression.Lambda(
Expression.SetProperty(instance, Expression.Cast(value, prop.PropertyType)),
instance, value
);
You would create and compile these expression trees once per instance type (typically in a static generic class).
While you're at it, you can probably make it even faster by compiling another expression tree instead of Activator.CreateInstance().

Member by Member copy

In an application we have we have a set of ORM objects, and a set of business object. Most of the time we're simply doing a member by member copy. Other times we process the data slightly. For instance:
tEmployee emp = new tEmployee();
emp.Name = obj.Name;
emp.LastName = obj.LastName;
emp.Age = obj.Age;
emp.LastEdited = obj.LastEdited.ToGMT();
Now this works just fine, and is rather fast, but not exactly terse when it comes to coding. Some of our objects have upto 40 members, so doing a copy like this can get rather tedious. Granted you only need 2 methods for two->from conversion, but I'd like to find a better way to do this.
Reflection is an natural choice, but on a benchmark I found that execution time was about 100x slower when using reflection.
Is there a better way to go about this?
Clarification:
I'm converting from one type to another. In the above example obj is of type BLogicEmployee and emp is of type tEmployee. They share member names, but that is it.
You might want to check out AutoMapper.
If you don't mind it being a bit slow the first time you can compile a lambda expression:
public static class Copier<T>
{
private static readonly Action<T, T> _copier;
static Copier()
{
var x = Expression.Parameter(typeof(T), "x");
var y = Expression.Parameter(typeof(T), "y");
var expressions = new List<Expression>();
foreach (var property in typeof(T).GetProperties())
{
if (property.CanWrite)
{
var xProp = Expression.Property(x, property);
var yProp = Expression.Property(y, property);
expressions.Add(Expression.Assign(yProp, xProp));
}
}
var block = Expression.Block(expressions);
var lambda = Expression.Lambda<Action<T, T>>(block, x, y);
_copier = lambda.Compile();
}
public static void CopyTo(T from, T to)
{
_copier(from, to);
}
}
Reflection can be sped up an awful lot if you use delegates. Basically, you can create a pair of delegates for each getter/setter pair, and then execute those - it's likely to go very fast. Use Delegate.CreateDelegate to create a delegate given a MethodInfo etc. Alternatively, you can use expression trees.
If you're creating a new object, I already have a bunch of code to do this in MiscUtil. (It's in the MiscUtil.Reflection.PropertyCopy class.) That uses reflection for properties to copy into existing objects, but a delegate to convert objects into new ones. Obviously you can adapt it to your needs. I'm sure if I were writing it now I'd be able to avoid the reflection for copying using Delegate.CreateDelegate, but I'm not about to change it :)
Consider using AutoMapper. From its documentation:
.. AutoMapper works best as long as
the names of the members match up to
the source type's members. If you have
a source member called "FirstName",
this will automatically be mapped to a
destination member with the name
"FirstName".
This will save you a great deal of explicit mapping, and AutoMapper of course allows for the customization of particular mappings along the lines of:
Mapper.CreateMap<Model.User, Api.UserInfo>()
.ForMember(s => s.Address, opt => opt.Ignore())
.ForMember(s => s.Uri, opt => opt.MapFrom(c => HttpEndpoint.GetURI(c)))
Object.MemberwiseClone might be useful if all you need is a shallow clone. Not sure how well it performs though, and obviously any complex objects would need additional handling to ensure a proper copy.
See if you can use this
RECAP:
and class must be Serializable for this to work.
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
Look att Automapper it can autmatically map your objects if your fields match...
http://automapper.codeplex.com/

List to Anonymous Type in c#

The short story: I want to convert a list/dictionary into an anonymous object
Basically what I had before was:
var model = from item in IEnumerable<Item>
select new
{
name = item.Name
value = item.Value
}
etc.
If I have name, item.Name in a list or dictionary, how can I go about creating the same anonymous object model?
Edit: Clarification:
If the dictionary contains [name, item.Name] and [value, item.Value] as Key Value pairs, how would I go about creating the model without assuming that you know neither name nor value?
Since a List<T> implements IEnumerable<T> your existing code should work exactly the same way:
var model = from item in yourList
select new { name = item.Name };
For a Dictionary<TKey,TValue> you could simply do this:
var model = from item in yourDictionary
select new {
name = item.Key
value = item.Value
};
This works because Dictionary<TKey,TValue> implements IEnumerable<KeyValuePair<TKey,TValue>> so in the second expression item will be typed as KeyValuePair<TKey,TValue> which means you can project a new type using item.Key and item.Value.
It sounds like you just want to get the values from a dictionary? If so, MyDictionary.Values should do the trick for you.
If you want to construct, somewhere else, another anonymous object, that is type-compatible with the one you generate from your IEnumerable<Item>, you can do that by ensuring that the anonymous type you construct has:
The same number of members
Members with the same type
Members with the same name
... in the same order
If you do that, they will map to the same single generated type.
Now, why you would want to do that is beyond me, so I'm pretty sure I didn't understand your question. You should post more information about what you want to do.
Anyway, here's the code to produce an anonymous object that is type-compatible with the one from your IEnumerable:
var x = new
{
name = dict["name"],
value = dict["value"]
};
Since this obeys all the rules above, it will be of the same type as your objects generated from your Linq query.

Categories