Reflection Performance - Create Delegate (Properties C#) - c#

I'm having performance problems with using reflection.
So I decided to create delegates for the properties of my objects and so far got this:
TestClass cwp = new TestClass();
var propertyInt = typeof(TestClass).GetProperties().Single(obj => obj.Name == "AnyValue");
var access = BuildGetAccessor(propertyInt.GetGetMethod());
var result = access(cwp);
static Func<object, object> BuildGetAccessor(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object), "o");
Expression<Func<object, object>> expr =
Expression.Lambda<Func<object, object>>(
Expression.Convert(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method),
typeof(object)),
obj);
return expr.Compile();
}
The results were highly satisfactory, about 30-40 times faster than using the conventional method (PropertyInfo.GetValue (obj, null);)
The problem is: How can I make a SetValue of a property, which works the same way? Unfortunately did not get a way.
I am doing so because I can not use methods with <T> because of the structure of my application.

This should work for you:
static Action<object, object> BuildSetAccessor(MethodInfo method)
{
var obj = Expression.Parameter(typeof(object), "o");
var value = Expression.Parameter(typeof(object));
Expression<Action<object, object>> expr =
Expression.Lambda<Action<object, object>>(
Expression.Call(
Expression.Convert(obj, method.DeclaringType),
method,
Expression.Convert(value, method.GetParameters()[0].ParameterType)),
obj,
value);
return expr.Compile();
}
Usage:
var accessor = BuildSetAccessor(typeof(TestClass).GetProperty("MyProperty").GetSetMethod());
var instance = new TestClass();
accessor(instance, "foo");
Console.WriteLine(instance.MyProperty);
With TestClass:
public class TestClass
{
public string MyProperty { get; set; }
}
Prints out:
foo

I think you'd be better off with CreateDelegate construct if performance is the key. Since you know the signature of the method beforehand, which here is just GetGetMethod and GetSetMethod of the PropertyInfo, you can create a delegate to execute the very method with the same signature directly. Expressions would be better suited if you need to build some logic (for which you did not have a method handle) to delegates. I did some benchmarking on different routes to this problem:
Func<S, T> Getter;
Action<S, T> Setter;
PropertyInfo Property;
public void Initialize(Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
Property = body.Member as PropertyInfo;
//approaches:
//Getter = s => (T)Property.GetValue(s, null);
//Getter = memberSelector.Compile();
//ParameterExpression inst = Expression.Parameter(typeof(S));
//Getter = Expression.Lambda<Func<S, T>>(Expression.Property(inst, Property), inst).Compile();
//var inst = Expression.Parameter(typeof(S));
//Getter = Expression.Lambda<Func<S, T>>(Expression.Call(inst, Property.GetGetMethod()), inst).Compile();
//Getter = (Func<S, T>)Delegate.CreateDelegate(typeof(Func<S, T>), Property.GetGetMethod());
//Setter = (s, t) => Property.SetValue(s, t, null);
//var val = Expression.Parameter(typeof(T));
//var inst = Expression.Parameter(typeof(S));
//Setter = Expression.Lambda<Action<S, T>>(Expression.Call(inst, Property.GetSetMethod(), val),
// inst, val).Compile();
//Setter = (Action<S, T>)Delegate.CreateDelegate(typeof(Action<S, T>), Property.GetSetMethod());
}
//Actual calls (tested under loop):
public T Get(S instance)
{
//direct invocation:
//return (T)Property.GetValue(instance, null);
//calling the delegate:
//return Getter(instance);
}
public void Set(S instance, T value)
{
//direct invocation:
//Property.SetValue(instance, value, null);
//calling the delegate:
//Setter(instance, value);
}
Results for about 10000000 calls - (Get, Set):
GetValue-SetValue (direct): 3800 ms, 5500 ms
GetValue-SetValue (delegate): 3600 ms, 5300 ms
compiled expressions:
Get: Expression.Property: 280 ms
Expression.Call: 280 ms
direct compile: 280 ms
Set: 300 ms
create delegate: 130 ms, 135 ms
direct property call: 70 ms, 70 ms
I would, in your case, write:
public static Func<S, T> BuildGetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetGetMethod().CreateDelegate<Func<S, T>>();
}
public static Action<S, T> BuildSetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetSetMethod().CreateDelegate<Action<S, T>>();
}
// a generic extension for CreateDelegate
public static T CreateDelegate<T>(this MethodInfo method) where T : class
{
return Delegate.CreateDelegate(typeof(T), method) as T;
}
public static PropertyInfo GetPropertyInfo<S, T>(this Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
return body.Member as PropertyInfo;
}
So now you call:
TestClass cwp = new TestClass();
var access = BuildGetAccessor((TestClass t) => t.AnyValue);
var result = access(cwp);
Isn't that simpler?? Had written a generic class here to handle the exact thing.

Use dynamic types. They use reflection under the hood, but they're a lot faster.
Otherwise...
There are tons of free faster reflection libraries out there with permissive licenses. I would link you, but there are too many, and I'm not sure which would suit you. Just search codeplex etc. When you find something you like, try it out.
But yeah, maybe before that, think if reflection really is the answer. Often there are other solutions.
Edit: As Requested...
http://geekswithblogs.net/SunnyCoder/archive/2009/06/26/c-4.0-dynamics-vs.-reflection.aspx
http://theburningmonk.com/2010/09/performance-test-dynamic-method-invocation-in-csharp-4/
http://www.mssoftwareconsulting.com/msswc/blog/post/C-40-and-dynamic-performance.aspx
It's common knowledge as far as I can tell.

Related

Is there a cleaner way to set Properties of Generic Classes?

Here's what I have so far, it works fine. Im just wondering if there is a smoother way to go about it:
public static PropertyInfo GetProperty<T, T2>(this Expression<Func<T, T2>> selectorExpression)
{
var memberExpression = selectorExpression.Body as MemberExpression;
if (memberExpression == null) throw new InvalidCastException();
return memberExpression.Member as PropertyInfo;
}
Here's an example function that can use it now. This one will set all selected values of objects in a list to something.
public static List<T> Set<T,T2>(this List<T> inList, decimal amount, Expression<Func<T, decimal>> valueSelector)
where T : class
{
var valueProperty = valueSelector.GetProperty();
foreach (var item in inList)
{
valueProperty.SetValue(item, amount);
}
return inList
}
Then I can simply just do this:
myList.Set(100, i => i.Value);
Where Value is some Setter property of the objects in MyList.
Now I know that second function is a super simple example. I am actually using GetProperty for way more complex stuff, specifically I have written a function that divies up a value amongst an IEnumerable to a selected setter property, based on a Getter 'weight' property in it.
The main thing I want to be discussing is my GetProperty function itself. Is there a better way to go about this or am I on the right track here already? Any kinds of further null checking or something I should be doing?
Just because the question was tagged C#-7.0, I thought of offering an answer with C#-7.0 features:
public static PropertyInfo GetProperty<TObject, TProperty>(
this Expression<Func<TObject, TProperty>> selectorExpression)
=> selectorExpression.Body is MemberExpression memberExpression
&& memberExpression.Member is PropertyInfo propertyInfo
? propertyInfo
: throw new InvalidCastException();
This works for me:
public static PropertyInfo GetProperty<T>(this Expression<Func<T, decimal>> selectorExpression)
{
var memberExpression = selectorExpression.Body as MemberExpression;
if (memberExpression == null) throw new InvalidCastException();
return memberExpression.Member as PropertyInfo;
}
Then, with this code, I get 42 written to the console:
void Main()
{
Expression<Func<Foo, decimal>> exp = q => q.Bar;
var p = exp.GetProperty();
var f = new Foo();
p.SetValue(f, 42m);
Console.WriteLine(f.Bar);
}
public class Foo
{
public decimal Bar { get; set; }
}

Create Expression Tree dynamically

I had an idea and want to know if it can work.
I have a simple classes with properties and want to generate accessors with Expressions.
But in the end I need to get a Func<Test, string> but I don't know the types when I use them.
A small example
class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.TestString = "Blubb";
var actionStub = typeof(Helper).GetMethod("CreatePropertyGetter").MakeGenericMethod(new Type[] { test.GetType(), typeof(string)});
dynamic action = actionStub.Invoke(null, new object[] {test.GetType(), "TestString"});
var x = action(test);
}
}
public class Test
{
public string TestString { get; set; }
}
public static class Helper
{
public static Func<TType, TPropValueType> CreatePropertyGetter<TType, TPropValueType>(Type type,
string propertyName)
{
PropertyInfo fieldInfo = type.GetProperty(propertyName);
ParameterExpression targetExp = Expression.Parameter(typeof(TType), "target");
MemberExpression fieldExp = Expression.Property(targetExp, fieldInfo);
UnaryExpression assignExp = Expression.Convert(fieldExp, typeof(TPropValueType));
Func<TType, TPropValueType> getter =
Expression.Lambda<Func<TType, TPropValueType>>(assignExp, targetExp).Compile();
return getter;
}
}
The problem is I cant call the expression without dynamic, because I cant simple cast it to Func<object, object>
You're generating (TType target) => target.Something. Instead, generate (object target) => (object)((TType)target).Something so that you can use Func<object, object>.
It's not clear what exactly you are asking for, but here is an example how you can make it Func<object, object>:
public static class Helper
{
public static Func<object, object> CreatePropertyGetter(Type type, string propertyName)
{
var fieldInfo = type.GetProperty(propertyName);
var targetExp = Expression.Parameter(typeof(object), "target");
var fieldExp = Expression.Property(Expression.ConvertChecked(targetExp, type), fieldInfo);
var getter = Expression.Lambda<Func<object, object>>(fieldExp,targetExp).Compile();
return getter;
}
}

C# FieldInfo reflection alternatives

I am currently using FieldInfo.GetValue and FieldInfo.SetValue quite a lot in my programm, which is significantly slowing up my programm.
For PropertyInfo I use the GetValueGetter and GetValueSetter methods so I only use reflection once for a given type. For the FieldInfo, the methods don't exist.
What is the suggested approach for FieldInfo?
EDIT:
I followed this useful link from CodeCaster's reply. This is a great search direction.
Now the "only" point that I don't get in this answer is how I can cache the getters / setters and re-use them in a generic way, using only the field's name - which is basically what the SetValue is doing
// generate the cache
Dictionary<string, object> setters = new Dictionary<string, object>();
Type t = this.GetType();
foreach (FieldInfo fld in t.GetFields()) {
MethodInfo method = t.GetMethod("CreateSetter");
MethodInfo genericMethod = method.MakeGenericMethod( new Type[] {this.GetType(), fld.FieldType});
setters.Add(fld.Name, genericMethod.Invoke(null, new[] {fld}));
}
// now how would I use these setters?
setters[fld.Name].Invoke(this, new object[] {newValue}); // => doesn't work without cast....
You could use Expressions to generate faster field accessors. If you want them to work on Object rather than the field's concrete type, you'd have to add casts (Convert) in the expression.
using System.Linq.Expressions;
class FieldAccessor
{
private static readonly ParameterExpression fieldParameter = Expression.Parameter(typeof(object));
private static readonly ParameterExpression ownerParameter = Expression.Parameter(typeof(object));
public FieldAccessor(Type type, string fieldName)
{
var field = type.GetField(fieldName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null) throw new ArgumentException();
var fieldExpression = Expression.Field(
Expression.Convert(ownerParameter, type), field);
Get = Expression.Lambda<Func<object, object>>(
Expression.Convert(fieldExpression, typeof(object)),
ownerParameter).Compile();
Set = Expression.Lambda<Action<object, object>>(
Expression.Assign(fieldExpression,
Expression.Convert(fieldParameter, field.FieldType)),
ownerParameter, fieldParameter).Compile();
}
public Func<object, object> Get { get; }
public Action<object, object> Set { get; }
}
Usage:
class M
{
private string s;
}
var accessors = new Dictionary<string, FieldAccessor>();
// expensive - you should do this only once
accessors.Add("s", new FieldAccessor(typeof(M), "s"));
var m = new M();
accessors["s"].Set(m, "Foo");
var value = accessors["s"].Get(m);

Reading Properties of an Object with Expression Trees

I want to create a Lambda Expression for every Property of an Object that reads the value dynamically.
What I have so far:
var properties = typeof (TType).GetProperties().Where(p => p.CanRead);
foreach (var propertyInfo in properties)
{
var getterMethodInfo = propertyInfo.GetGetMethod();
var entity = Expression.Parameter(typeof (TType));
var getterCall = Expression.Call(entity, getterMethodInfo);
var lambda = Expression.Lambda(getterCall, entity);
var expression = (Expression<Func<TType, "TypeOfProperty">>) lambda;
var functionThatGetsValue = expression.Compile();
}
The code Works well when i call functionThatGetsValue as long as "TypeOfProperty" is hardcoded. I know that I can't pass the "TypeOfPoperty" dynamically. What can I do to achive my goal?
Assuming that you're happy with a Func<TType, object> delegate (as per the comments above), you can use Expression.Convert to achieve that:
var properties = typeof(TType).GetProperties().Where(p => p.CanRead);
foreach (var propertyInfo in properties)
{
MethodInfo getterMethodInfo = propertyInfo.GetGetMethod();
ParameterExpression entity = Expression.Parameter(typeof(TType));
MethodCallExpression getterCall = Expression.Call(entity, getterMethodInfo);
UnaryExpression castToObject = Expression.Convert(getterCall, typeof(object));
LambdaExpression lambda = Expression.Lambda(castToObject, entity);
var functionThatGetsValue = (Func<TType, object>)lambda.Compile();
}
After hours of googling found the answer here. I've added the snippets from the blog post as it might help others having the same troubles:
public static class PropertyInfoExtensions
{
public static Func<T, object> GetValueGetter<T>(this PropertyInfo propertyInfo)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
return (Func<T, object>)Expression.Lambda(convert, instance).Compile();
}
public static Action<T, object> GetValueSetter<T>(this PropertyInfo propertyInfo)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var argument = Expression.Parameter(typeof(object), "a");
var setterCall = Expression.Call(
instance,
propertyInfo.GetSetMethod(),
Expression.Convert(argument, propertyInfo.PropertyType));
return (Action<T, object>)Expression.Lambda(setterCall, instance, argument).Compile();
}
}
I've modified gsharp's post above to actually set the value directly and make it a bit easier to use. It's not ideal as there is the introduction of the DynamicCast function which requires you to know your type up front. My goal was to try to keep us strongly typed and not return object and avoid dynamic keyword. Also, keep "magic" to a minimum.
public static T DynamicCast<T>(this object value)
{
return (T) value;
}
public static object GetPropertyValue<T>(this PropertyInfo propertyInfo, T objectInstance)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, propertyInfo.PropertyType);
var lambda = Expression.Lambda(convert, instance).Compile();
var result = lambda.DynamicInvoke(objectInstance);
return result;
}
public static void SetPropertyValue<T, TP>(this PropertyInfo propertyInfo, T objectInstance, TP value)
where T : class
where TP : class
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var argument = Expression.Parameter(propertyInfo.PropertyType, "a");
var setterCall = Expression.Call(
instance,
propertyInfo.GetSetMethod(),
Expression.Convert(argument, propertyInfo.PropertyType));
var lambda = Expression.Lambda(setterCall, instance, argument).Compile();
lambda.DynamicInvoke(objectInstance, value);
}
Examples:
public void Get_Value_Of_Property()
{
var testObject = new ReflectedType
{
AReferenceType_No_Attributes = new object(),
Int32WithRange1_10 = 5,
String_Requires = "Test String"
};
var result = testObject.GetType().GetProperty("String_Requires").GetPropertyValue(testObject).DynamicCast<string>();
result.Should().Be(testObject.String_Requires);
}
public void Set_Value_Of_Property()
{
var testObject = new ReflectedType
{
AReferenceType_No_Attributes = new object(),
Int32WithRange1_10 = 5,
String_Requires = "Test String"
};
testObject.GetType().GetProperty("String_Requires").SetPropertyValue(testObject, "MAGIC");
testObject.String_Requires.Should().Be("MAGIC");
}
You could write a helper method which uses MakeGenericMethod or an expression tree to make a lambda do the typed call to call DynamicCast based on the PropertyInfo object and avoid having to know it up front. But that is less elegant.

Listing object properties like the Visual Studio Immediate window

I store a few classes in session. I want to be able to see the values of my class properties in trace viewer. By default I only the Type name MyNamespace.MyClass. I was wondering if I overwrite the .ToString() method and use reflection to loop over all the properties and construct a string like that ... it would do the trick but just wanted to see if there is anything already out there (specially since Immediate Window has this capability) which does the same ... i.e. list the class property values in trace instead of just the Name of the class.
You can try something like that:
static void Dump(object o, TextWriter output)
{
if (o == null)
{
output.WriteLine("null");
return;
}
var properties =
from prop in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
where prop.CanRead
&& !prop.GetIndexParameters().Any() // exclude indexed properties to keep things simple
select new
{
prop.Name,
Value = prop.GetValue(o, null)
};
output.WriteLine(o.ToString());
foreach (var prop in properties)
{
output.WriteLine(
"\t{0}: {1}",
prop.Name,
(prop.Value ?? "null").ToString());
}
}
Of course, it's not very efficient because of the reflection... A better solution would be to dynamically generate and cache a dumper method for each specific type.
EDIT: here's an improved solution, that uses Linq expressions to generate a specialized dumper method for each type. Slightly more complex ;)
static class Dumper
{
private readonly static Dictionary<Type, Action<object, TextWriter>> _dumpActions
= new Dictionary<Type, Action<object, TextWriter>>();
private static Action<object, TextWriter> CreateDumper(Type type)
{
MethodInfo writeLine1Obj = typeof(TextWriter).GetMethod("WriteLine", new[] { typeof(object) });
MethodInfo writeLine1String2Obj = typeof(TextWriter).GetMethod("WriteLine", new[] { typeof(string), typeof(object), typeof(object) });
ParameterExpression objParam = Expression.Parameter(typeof(object), "o");
ParameterExpression outputParam = Expression.Parameter(typeof(TextWriter), "output");
ParameterExpression objVariable = Expression.Variable(type, "o2");
LabelTarget returnTarget = Expression.Label();
List<Expression> bodyExpressions = new List<Expression>();
bodyExpressions.Add(
// o2 = (<type>)o
Expression.Assign(objVariable, Expression.Convert(objParam, type)));
bodyExpressions.Add(
// output.WriteLine(o)
Expression.Call(outputParam, writeLine1Obj, objParam));
var properties =
from prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
where prop.CanRead
&& !prop.GetIndexParameters().Any() // exclude indexed properties to keep things simple
select prop;
foreach (var prop in properties)
{
bool isNullable =
!prop.PropertyType.IsValueType ||
prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
// (object)o2.<property> (cast to object to be passed to WriteLine)
Expression propValue =
Expression.Convert(
Expression.Property(objVariable, prop),
typeof(object));
if (isNullable)
{
// (<propertyValue> ?? "null")
propValue =
Expression.Coalesce(
propValue,
Expression.Constant("null", typeof(object)));
}
bodyExpressions.Add(
// output.WriteLine("\t{0}: {1}", "<propertyName>", <propertyValue>)
Expression.Call(
outputParam,
writeLine1String2Obj,
Expression.Constant("\t{0}: {1}", typeof(string)),
Expression.Constant(prop.Name, typeof(string)),
propValue));
}
bodyExpressions.Add(Expression.Label(returnTarget));
Expression<Action<object, TextWriter>> dumperExpr =
Expression.Lambda<Action<object, TextWriter>>(
Expression.Block(new[] { objVariable }, bodyExpressions),
objParam,
outputParam);
return dumperExpr.Compile();
}
public static void Dump(object o, TextWriter output)
{
if (o == null)
{
output.WriteLine("null");
}
Type type = o.GetType();
Action<object, TextWriter> dumpAction;
if (!_dumpActions.TryGetValue(type, out dumpAction))
{
dumpAction = CreateDumper(type);
_dumpActions[type] = dumpAction;
}
dumpAction(o, output);
}
}
Usage:
Dumper.Dump(myObject, Console.Out);
This is the code I use. I find it incredibly useful and is almost instant. The code is using the Newtonsoft JSON converter.
[System.Obsolete("ObjectDump should not be included in production code.")]
public static void Dump(this object value)
{
try
{
System.Diagnostics.Trace.WriteLine(JsonConvert.SerializeObject(value, Formatting.Indented));
}
catch (Exception exception)
{
System.Diagnostics.Trace.WriteLine("Object could not be formatted. Does it include any interfaces? Exception Message: " + exception.Message);
}
}
Add this to a common library, reference it and add it to the using clause. Can be used in the immediate window by typing YourObject.Dump() (the exact same as you'd do in linqpad).
Classes including interfaces have to be handled differently as this is simply a JSON converter. A workaround for classes that include interface implementations that I use is to remove the default empty constructor and implement a constructor using the specific instances of the interfaces.
I find JSON a very easy format to read and consider this small method invaluable for debugging.

Categories

Resources