Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About ComponentModel and Reflection

Tags:

c#

reflection

I have a function that accepts any object, then it gets values from the properties or fields that it has as input.

It currently looks like this:

private string GetFieldValue(object o, Field f)
{
 //field.name is name of property or field
        MemberInfo[] mi = o.GetType().GetMember(field.name, MemberTypes.Field | MemberTypes.Property,
            BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | 
            BindingFlags.ExactBinding );

        if (mi.Length == 0) throw new ArgumentException("Field", "Can't find member: " + f.name);

        Object value;
        if (mi[0].MemberType == MemberTypes.Property)
             value = ((PropertyInfo)mi[0]).GetValue(o, null);
        else value = ((FieldInfo)mi[0]).GetValue(o);

Today I read about System.ComponentModel and its XXXDescriptor classes. What is the difference, when performance is in question, between 2 frameworks (Reflection & ComponentModel). Will rewriting the above using ComponentModel achieve better performance or flexibility ? The only other difference between those two that I know is support for virtual properties by CM.

Ty.

like image 950
majkinetor Avatar asked Jan 23 '23 15:01

majkinetor


2 Answers

The difference is that ComponentModel is an abstraction over raw classes. This means that you can define properties that don't exist - and indeed, that is exactly how DataView / DataRowView expose columns as properties for data binding. Using ComponentModel, the, you can get something like "dynamic" even in 1.1.

You might think that means that ComponentModel is slower; but actually, you can exploit this abstraction for gain... HyperDescriptor does exactly that - using Reflection.Emit to write direct IL to represent properties, giving much faster access than either reflection or vanilla ComponentModel.

Note, however, that ComponentModel is, by default, limited to properties (not fields). You can do it via on-the-fly PropertyDescriptor facades, but it isn't a good idea. There also isn't much place for a "write only" property in ComponentModel.

like image 94
Marc Gravell Avatar answered Feb 04 '23 10:02

Marc Gravell


TypeDescriptor (in System.ComponentModel) caches internally, so it can have better performance, though there's nothing stopping you adding a cache to the above code. TypeDescriptor uses reflection, although it allows you to extend your object and add properties and events that aren't backed by 'real' properties and events. TypeDescriptor doesn't support fields, however.

If I were you, and I didn't care about TypeDescriptor's extensibility features, and I was happy to add your own cache on top of GetMember, then I'd stick with reflection.

Edit: Standard reflection has cached MemberInfo objects since 2.0 -- see MSDN "Using .NET: Avoid Common Performance Pitfalls for Speedier Apps".

like image 44
Tim Robinson Avatar answered Feb 04 '23 11:02

Tim Robinson