views:

1004

answers:

5

I've been told to use Reflection.Emit instead of PropertyInfo.GetValue / SetValue because it is faster this way. But I don't really know what stuff from Reflection.Emit and how to use it to substitute GetValue and SetValue. Can anybody help me with this ?

+1  A: 

The purpose of Reflection.Emit is completely different from that of PropertyInfo.Get/SetValue. Via Reflection.Emit, you can directly emit IL code, for example into dynamically compiled assemblies, and execute this code. Of course, this code could access your properties.

I seriously doubt that this will be much quicker then using PropertyInfo in the end, and it's not made for this purpose either. You could use Reflection.Emit as the code generator for a small compiler, for example.

Maximilian Mayerl
+1  A: 

Using Reflection.Emit seems a little too "clever", as well as a premature optimization. If you profile your application, and you find that the GetValue/SetValue Reflection is the bottleneck, then you could consider optimizing, but probably not even then...

John Buchanan
+6  A: 

Use PropertyInfo.GetValue/SetValue

If you have performance problems cache the PropertyInfo object (don't repeatedly call GetProperty)

If - and only if - the use of reflection is the performance bottleneck of your app (as seen in a profiler) use Delegate.CreateDelegate

If - and really really only if - you are absolutely sure that reading/writing the values is still the worst bottleneck it's time to start learning about the fun world of generating IL in runtime.

I really doubt it's worth it, each of those levels increase the complexity of the code more then they improve performance - do them only if you have to.

And if runtime access to properties is your performance bottleneck it's probably better going for compile time access (it's hard time to be both generic and super high performance at the same time).

Nir
But doable: http://www.codeproject.com/KB/cs/HyperPropertyDescriptor.aspx
Marc Gravell
+3  A: 

If you're fetching/setting the same property many times, then using something to build a typesafe method will indeed be faster than reflection. However, I would suggest using Delegate.CreateDelegate instead of Reflection.Emit. It's easier to get right, and it's still blazingly fast.

I've used this in my Protocol Buffers implementation and it made a huge difference vs PropertyInfo.GetValue/SetValue. As others have said though, only do this after proving that the simplest way is too slow.

I have a blog post with more details if you decide to go down the CreateDelegate route.

Jon Skeet
Very interesting - I tried creating a delegate to FieldInfo.SetValue, and it changed absolutely nothing. Fairly obvious really, since all I did was change the way the function is called, and it's the function itself that's slow.So how did you get this performance increase ? I had no luck finding information about it in your blog post (maybe I'm just blind :-D)
Steffen
Just re-read your blog entry and spotted the GetGetMethod and GetSetMethod part, apparently I *were* blind before.Anyway this obviously explains the speed difference, however for FieldInfos I'm still in the dark :-SI'm however looking forward to Marcs example :-)Just wanted to let you know I found out what you did to speed up things through delegates.
Steffen
Cheers (+1) - I just used that idea to save .1s - .8s per page on some reflection populated classes :-)
Keith
+3  A: 

Just an alternative answer; if you want the performance, but a similar API - consider HyperDescriptor; this uses Reflection.Emit underneath (so you don't have to), but exposes itself on the PropertyDescriptor API, so you can just use:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(obj);
props["Name"].SetValue(obj, "Fred");
DateTime dob = (DateTime)props["DateOfBirth"].GetValue(obj);

One line of code to enable it, and it handles all the caching etc.

Marc Gravell
what do you mean by "use HyperDescriptor per the download" ? i just need to get properties, get and set values to them, that's all
Omu
I mean you need to download the HyperDescriptor component from codeproject and enable it as shown in the page (several different ways). *Without* HyperDescriptor this is jut glorified reflection; HyperDescriptor intercepts TypeDescriptor and replaces the reflection code with dynamic IL.
Marc Gravell
It is confusing, I agree; the same code works fine with/without HyperDescriptor, but it is /much/ (~100x) slower without. Any problems getting it working, let me know (it was a few years ago when I wrote it, but I still remember most of it!)
Marc Gravell
Could you show me how to use it without using the Attributes for classes ?
Omu
Ok, I found something, I do HyperTypeDescriptionProvider.Add(typeof(Foo)); HyperTypeDescriptionProvider.Add(typeof(Bar)); at the start of the application
Omu
That's the one ;-p
Marc Gravell
This is exactly what I've been looking for, however I have a question: Could this somehow be extending to handle fields as well as properties ?AFAIK there's no TypeDescriptor.GetFields method (or similar for that matter) So i'm wondering if you could hook into FieldInfo.SetValue and GetValue instead ?
Steffen
In principal you could; what level of functionality do you need? Just read or write can be done with `DynamicMethod` or `Expression`. What do you need? Does it have to be a `PropertyDescriptor`, for example?
Marc Gravell
It's just read and write I need really, currently I use FieldInfo.SetValue and FieldInfo.GetValue (as well as PropertyInfo.SetValue and GetValue, in case there are properties in the reflected class)It doesn't have to a PropertyDescriptor - in fact I'd probably prefer it isn't, as I'm not using PropertyDescriptors at the moment.It's for a DB access lib, which uses reflection for setting the proper fields/properties upon selecting data from the database.Basically a reflected version ofthis.Id = (int)dr["Id"]; // dr is a DataRow
Steffen