My use case can have thousands of instances of a class. One of the properties in that class is also of the same type as that of a class and this can go on and on.
So I basically have a collection of nested classes. Now if I were to search a property's value, what would my options be.
I am finding recurssion as one(Getting Nested Object Property Value Using Reflection) and an exhaustive use of GetNestedTypes(https://msdn.microsoft.com/en-us/library/493t6h7t(v=vs.110).aspx) as other.
I read that reflection is expensive, so my question is, are there other ways to search the property without using reflection concept?
You can use expression trees to create an abstract syntax tree that you can then compile to a dynamic method. This performs very closely to regularly written code (from my testing it is many times faster then reflection). The creation of the dynamic method is expensive, so create once, use many times.
static Func<object,object> CreateDelegate(PropertyInfo[] path)
{
var rootType = path.First().DeclaringType;
var param = Expression.Parameter(typeof(object));
Expression access = Expression.Convert(param, rootType);
foreach (var prop in path)
{
access = Expression.MakeMemberAccess(access, prop);
}
var lambda = Expression.Lambda<Func<object, object>>(
Expression.Convert(access, typeof(object)),
param
).Compile();
return lambda;
}
static void Main(string[] args)
{
var path = new[]
{
typeof(Root).GetProperty("Level1"),
typeof(Level1).GetProperty("Level2"),
typeof(Level2).GetProperty("Name")
};
var method = CreateDelegate(path);
var data = new Root { Level1 = new Level1 { Level2 = new Level2 { Name = "Test" } } };
var result = method(data);
}
References: Dynamic Methods, Expression Tree-Compile
Related
I have a table called "Account." Account has 3 columns: id, acct_name, is_privileged.
When I write something like "account.", visual studio provides me with a list of attributes/methods I can use. Hence, I get the option of using account.id, account.acct_name, and account.is_privileged.
However, I would like to change a particular column's value dynamically, without typing in my column's name. I am getting the column's name dynamically as a string variable. Is it possible to achieve it? If so, how?
My code is as follows:
set_col_name = rowRule.Cells["setcolumnnameDataGridViewTextBoxColumn"].Value.ToString();
set_col_value = rowRule.Cells["setcolumnvalueDataGridViewTextBoxColumn"].Value.ToString();
foreach (DataGridViewRow rowAcc in dgvAccount.Rows)
{
if (isComparable(rowAcc.Cells[col_name].Value.ToString(), comp_operator, col_value))
{
account.id = (int)rowAcc.Cells["idDataGridViewTextBoxColumn2"].Value;
using (ae = new AccountEntities())
{
var temp = ae.Accounts.SingleOrDefault(a => a.id == account.id);
temp.is_privileged = set_col_value; //learn how to do this dynamically
ae.SaveChanges();
}
}
}
Where I do temp.is_privileged, I'd like to achieve something like, temp."set_col_name" = set_col_value;
Instead of specifying the column name directly as being "is_privileged" in this case, I'd like to pass a string to specify it.
Thank you.
If I understand your problem statement correctly, you want something like this to work:
Account temp = // with temp coming from a library such as EntityFramework
temp.SetValue(set_col_name, set_col_value);
this is quite easy to achieve with either pure reflection or Linq Expression Trees (which I opted for):
static class Ext
{
public static void Set<T, TProperty>(this T instance, string propertyName, TProperty value)
{
var instanceExpression = Expression.Parameter(typeof(T), "p");
var propertyGetterExpression = Expression.PropertyOrField(instanceExpression, propertyName);
//generate setter
var newValueExpression = Expression.Parameter(typeof(TProperty), "value");
var assignmentExpression = Expression.Assign(propertyGetterExpression, newValueExpression);
var lambdaExpression = Expression.Lambda<Action<T, TProperty>>(assignmentExpression, instanceExpression, newValueExpression);
var setter = lambdaExpression.Compile();// the generated lambda will look like so: (p, value) => p.{your_property_name} = value;
setter(instance, value);
}
}
one advantage of this method over pure reflection is that you can build the setter delegate once and call it multiple times at later stage (I will leave this with you to experiment)
with the above in place, hopefully you should be able to do something like this:
var set_col_name = "is_privileged";
var set_col_value = true;
using (ae = new AccountEntities())
{
var temp = ae.Accounts.SingleOrDefault(a => a.id == account.id);
temp.Set(set_col_name, set_col_value);
temp.Set("acct_name", "test");
ae.SaveChanges();
}
You need some reflection in this one. For example
public static void CopyValues<T>(T obj1, T obj2)
{
var type = typeof(T);
foreach (var prop in type.GetProperties())
{
prop.SetValue(obj1, prop.GetValue(obj2));
}
}
And use the above function like this:
var source = new Accounts(){is_privileged = false};
var destiny = new Accounts();
CopyValues(source, destiny);
It depends of what you are loking for, but the key is to use REFLECTION!
I am trying to dynamically generate a class that implements a given interface. Because of this, I need to implement some methods. I would like to avoid directly emitting IL instructions, so I am trying to use Expression trees and CompileToMethod. Unfortunately, some of these methods need to access a field of the generated class (as if I wrote this.field into the method I am implementing). Is it possible to access "this" using expression trees? (By "this" I mean the object the method will be called on.)
If yes, what would a method like this look like with expression trees?
int SomeMethod() {
return this.field.SomeOtherMethod();
}
Expression.Constant or ParameterExpression are your friends; examples:
var obj = Expression.Constant(this);
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<int>>(call);
or:
var obj = Expression.Parameter(typeof(SomeType));
var field = Expression.PropertyOrField(obj, "field");
var call = Expression.Call(field, field.Type.GetMethod("SomeOtherMethod"));
var lambda = Expression.Lambda<Func<SomeType, int>>(call, obj);
(in the latter case, you'd pass this in as a parameter, but it means you can store the lambda and re-use it for different target instance objects)
Another option here might be dynamic if your names are fixed:
dynamic obj = someDuckTypedObject;
int i = obj.field.SomeOtherMethod();
I'm using a combination of reflection and expression trees, and want to pass back certain property accessors from a class to a calling method. My current code has a method traversing the class and returning a list of MemberExpressions. The caller then iterates over the member expressions and creates lambdas, which should then be called with an instance of the inspected class to return the value of the property.
Here is a sample of what it would look like without the method calls (Runnable in LINQPad):
void Main()
{
var t = new Test { Prop = "Test" };
var property = t.GetType().GetProperty("Prop");
var baseType = Expression.Parameter(typeof(Test), "baseType");
var memberAccess = Expression.MakeMemberAccess(baseType, property);
var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, Expression.Parameter(typeof(Test), "baseType"));
var func = lambda.Compile();
var result = func(t);
result.Dump();
}
class Test {
public string Prop { get; set; }
}
This does not work, throwing this exception:
InvalidOperationException: variable 'baseType' of type 'UserQuery+Test' referenced from scope '', but it is not defined
However, if I change the creation of the lambda to this:
var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, baseType);
That is, replace the Expression.Parameter with the variable used earlier, then it works. This is not (easily) possible in the scenario where I want to use it, since I would have to return the original parameter along with the list (I could return a tuple, of course, but I would prefer not to, if it is not necessary).
Why does it work like this? Inspecting the DebugView of the lambda, they are exactly the same no matter what approach is used:
.Lambda #Lambda1<System.Func`2[UserQuery+Test,System.String]>(UserQuery+Test $baseType)
{
$baseType.S
}
Yes, you need to refer ParameterExpression, used earlier. This won't compile too:
private String Foo(Test myParam)
{
return myAnotherParam.MyProperty;
}
With instatiating new ParameterExpression in lambda, you're doing the same thing (but note, when making lambda, you're doing it in reversed order - first, you're constructing a method body, then - a method declaration):
// return myAnotherParam.MyProperty;
var baseType = Expression.Parameter(typeof(Test), "baseType");
var memberAccess = Expression.MakeMemberAccess(baseType, property);
// private String Foo(MyClass myParam)
var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, Expression.Parameter(typeof(Test), "baseType"));
I have an assembly and some classes. What I'm trying to do is create an instance of a class and fill its properties in a generic way, something like:
public T FillObject(IDictionary<string,object> values)
{
/// CREATE INSTANCE
/// FILL THE PROPERTIES WITH THE VALUES
}
Reflection is the best way but its too slow, instead I've heard that Reflection.Emit is faster, so, is there a way to instantiate the class and fill its properties with Reflection.Emit?
Thanks in advance for any help.
On this occasion, I suggest HyperDescriptor; it is like reflection, but with IL generation thrown in the middle for performance; then, you just use regular component-model code:
object obj = Activator.CreateInstance(typeof(T));
var props = TypeDescriptor.GetProperties(typeof(T));
foreach(var pair in data)
{
props[pair.Key].SetValue(obj, pair.Value);
}
Edit; for a bit of a 2012 update, FastMember involves less abstraction:
var accessor = TypeAccessor.Create(typeof(T));
foreach(var pair in data)
{
accessor[obj, pair.Key] = pair.Value;
}
In addition to being more direct, FastMember will work with properly dynamic types, too - not just reflection.
If you're on .Net 4, you could use the new Expression types (that were added to support dynamic), to create an expression that assigns the properties, compile it to a delegate once, and call that repeatedly. The performance should be comparable with using Reflection.Emit.
class ObjectFiller<T>
{
private static Func<IDictionary<string, object>, T> FillerDelegate;
private static void Init()
{
var obj = Expression.Parameter(typeof(T), "obj");
var valuesDictionary = Expression.Parameter(typeof(IDictionary<string, object>), "values");
var create = Expression.Assign(
obj, Expression.Call(typeof(Activator), "CreateInstance", new[] { typeof(T) }));
var properties = typeof(T).GetProperties();
var setters = Expression.Block(properties.Select(p => CreateSetter(p, obj, valuesDictionary)));
var methodBody = Expression.Block(typeof(T), new[] { obj }, create, setters, obj);
var fillerExpression = Expression.Lambda<Func<IDictionary<string, object>, T>>(methodBody, valuesDictionary);
FillerDelegate = fillerExpression.Compile();
}
static Expression CreateSetter(PropertyInfo property, Expression obj, Expression valuesDictionary)
{
var indexer = Expression.MakeIndex(
valuesDictionary,
typeof(IDictionary<string, object>).GetProperty("Item", new[] { typeof(string) }),
new[] { Expression.Constant(property.Name) });
var setter = Expression.Assign(
Expression.Property(obj, property),
Expression.Convert(indexer, property.PropertyType));
var valuesContainsProperty = Expression.Call(
valuesDictionary, "ContainsKey", null, Expression.Constant(property.Name));
var condition = Expression.IfThen(valuesContainsProperty, setter);
return condition;
}
public T FillObject(IDictionary<string, object> values)
{
if (FillerDelegate == null)
Init();
return FillerDelegate(values);
}
}
You could do something very similar in .Net 3 too, using the Expression version of object initializers.
Dapper.NET does this. It's a Micro-ORM made to power stackoverflow. The whole ORM is just one C# file.
http://code.google.com/p/dapper-dot-net/source/browse/Dapper/SqlMapper.cs
The relevant code that creates the dynamic method is this:
var method = new DynamicMethod(commandType.Name + "_BindByName", null, new Type[] { typeof(IDbCommand), typeof(bool) });
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, commandType);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Callvirt, setter, null);
il.Emit(OpCodes.Ret);
action = (Action<IDbCommand, bool>)method.CreateDelegate(typeof(Action<IDbCommand, bool>));
Also note that the IKVM.NET project provides their own implementation of IKVM.Reflection.Emit with a number of enhancements. If you're starting from scratch it might be good to look at that as an alternative.
Here is an example article on how to do mapping from a database IDatarecord.
Its easy to adapt this to most scenarios
Dynamic... But Fast: The Tale of Three Monkeys, A Wolf and the DynamicMethod and ILGenerator Classes
http://www.codeproject.com/KB/database/DynamicMethod_ILGenerator.aspx
I'm writing a file generic block for my application and started with using Lambda expressions for managing my rule sets for block generation to avoid the pitfalls of magic strings, configuration hell etc.
Inside my mapping class I have lines similar to:
Map(x => x.Name).Length(20).PadLeft(true).PaddingChar("#");
This works fine and isn't where my question dwells, where I setup saving my information about the expression is in the Map method:
public override IPropertyMap Map(Expression<Func<T, object>> expression)
{
var propertyMap = new FixedLengthPropertyMap
{
//Length = 20,
//PaddingCharacter = " ",
PadLeft = false,
PropertyInfo = ReflectionHelper.GetProperty(expression)
};
_properties.Add(propertyMap);
return propertyMap;
}
_properties is just a List<IPropertyMap> that stores my info where my question from what is the best way to have a real object's data be read from the properties currently I came up with something similar to this:
var map = new AgentMap();
var agent = new Agent {Name = "Bob"};
string output = map.Write(agent);
public override string Write<T>(T agent)
{
var initial = _properties[0];
return initial.PropertyInfo.GetValue(agent, null) as string;
}
Is there a better way than using the GetValue method since earlier on I'm using an expression tree?
I don't see why you really need to use expression trees at all. Just make the Map method take a Func<T, object> and store that:
public override IPropertyMap Map(Func<T, string> fetcher)
{
var propertyMap = new FixedLengthPropertyMap
{
//Length = 20,
//PaddingCharacter = " ",
PadLeft = false,
Delegate = fetcher // Delegate is of type Delegate
};
_properties.Add(propertyMap);
return propertyMap;
}
Then:
public override string Write<T>(T agent)
{
var initial = _properties[0];
Func<T, string> fetcher = (Func<T, string>) initial.Delegate;
return fetcher(agent);
}
Is there any reason you particularly wanted to know the property and use an expression tree?
In part, it depends on what your scenario is. The "simple" answer is to just compile the expression and invoke it, but that has a potential performance impact if you are doing it in a tight loop (passing a delegate would be a lot quicker).
I'm not sure whether if would apply in this particular case (because of the agent), but to avoid doing too much expression compilation, you can look for simple scenarios and read the value directly from the expression tree; a little bit of PropertyInfo/FieldInfo is going to be quicker than compiling it...
For more, look at TryEvaluate here, and how it is used with Compile as a backup strategy (although you have the advantage of a known delegate type).