Reflection: Setting properties of lots of objects using Dynamic Methods - c#

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().

Related

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.

Handling lambda expression with generic property name

Working with EPiServer Find and trying to build a generic facet funcionality for it to simplify managing which facet should be enabled. I would like to construct two generic methods, one for adding active filters to perform the hits search and one to perform the available facet filters remaining.
The first method will perform the following (specific code for brand filter):
var brandFilter = client.BuildFilter<FashionProduct>();
foreach (var facet in SelectedGroup.Facets.Where(x => x.Selected))
{
brandFilter = brandFilter.Or(x => x.Brand.Match(facet.Key));
}
query = query.Filter(brandFilter);
I would like to be able to call it in a generic way so I could base the available facets on some simple list of strings or objects. Like this:
query = AddFilterFacet<FashionProduct>(query, "Brand", SelectedGroup.Facets)
So the method would take the type of object to filter on, the query to append the filters on, the name of the property to filter on and the list of values to add.
The second method is similar but relates more to perform the following:
facetQuery = facetQuery.TermsFacetFor(x => x.Brand)
...
var brandFacets = facetResult.TermsFacetFor(x => x.Brand).Terms;
Is it possible to build this kind of functionality? The biggest questionmark I have is how to translate the "Brand" input string to be the Brand Property in x => x.Brand
private void AddFilterFacet<T>(IClient client, ref ITypeSearch<T> query, string propertyName, List<FacetOption> facets)
{
var filter = client.BuildFilter<T>();
foreach (var facet in facets)
{
filter = filter.Or(x => x.????.Match(facet.Key));
}
query = query.Filter(filter);
}
The .Or method takes a
System.Linq.Expressions.Expression<Func<T, Find.Api.Querying.Filter>>
so perhaps something can be used to make a proper generic call to it
It's definitely possible to create generic lambda expressions, it's just not easy and requires a lot of reflection code.
I haven't done it in a while, but maybe if you look at the code i created for something similar a while ago (Generic lambda expressions) it'll help. I'm sure someone with fresher experience will help you out here soon enough.
Decimal precision attribute <-- take a look a this answer witch has code to genereate modelBuilder.Entity<CLASS>().Property(OBJECT=> OBJECT.PROPERTY).HasPrecision(12, 10) automatically from an attribute in a class

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

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.

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/

.net 3.5 anonymous foreach

I'm trying to loop through the results of a function that is returning an anonymous object of results.
public static object getLogoNav()
{
XDocument loaded = XDocument.Load(HttpContext.Current.Request.MapPath("~/App_Data/LOGO_NAV_LINKS.xml"));
var query = from x in loaded.Elements().Elements()
select new
{
Name = x.FirstAttribute.Value,
Value = x.Value
};
return query;
}
codebehind page:
var results = Common.getLogoNav();
foreach(var nav in results) {
string test = nav.Name;
}
You can't have an anonymous class as a return type in C# 3 (and 4 for that matter) and you can't cast an object to an anonymous type. Your three options are:
Doing the loop within the scope of the anonymous class (most of the time, this is the method)
Casting to object and using reflection (slow and not very easy to do unless you do some expression tree magic)
Converting to a named class and returning and instance of that.
(In C# 4) you can create some dynamic type magic to achieve a similar effect but that would be really the same as option 2 with some syntactic sugar.
Jon Skeet wrote an entry about returning anonymous type. I hope you don't use it.

Categories