I ran into an interesting problem today. I posted code for a handful of very useful Reflection helper routines I use to dynamically access properties/fields and call methods on .Net objects. This has been working great in many situations where you’re dealing with dynamically created objects and objects accessed indirectly through remoting or other remote mechanism when no interfaces are available.
While working on my Help Builder Add in for VS.Net I ran into a fairly serious problem with this code – the issue is that code using the MemberInfo structures that are trying to read the property and method signatures dynamically are failing. For example the following code to GetProperty:
public const BindingFlags MemberAccess =
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase;
public static object GetProperty(object Object,string Property)
{
PropertyInfo pi = Object.GetType().GetProperty(Property,
wwUtils.MemberAccess | BindingFlags.GetProperty);
return pi.GetValue(Object,null);
}
failed with a dynamically create EXE COM server:
private bool LoadHelpBuilder(ref object HelpBuilder)
{
if (HelpBuilder == null)
{
Type loT = Type.GetTypeFromProgID("wwHelp.wwHelp");
HelpBuilder = Activator.CreateInstance(loT);
}
try
{
object nHtmlFormat = wwUtils.GetProperty(HelpBuilder,"nhtmlformat");
}
catch(Exception ex)
{
// *** Nope try reloading
HelpBuilder = null;
return LoadHelpBuilder(ref HelpBuilder);
}
return true;
}
In this example, GetProperty() fails with Invalid Object reference – which I presume means that the object contains no matching signature as far as Reflection is concerned.
However, it turns out that using InvokeMember() like this work in the GetProperty method:
public static object GetProperty(object Object,string Property)
{
return Object.GetType().InvokeMember(Property,
wwUtils.MemberAccess | BindingFlags.GetProperty,null,
Object,null);
}
Although it works my question is what is InvokeMember doing that GetProperty() is not. I tried playing around with the various MemberInfo flags to see if that would possibly get it to work, but couldn’t. Anybody know what InvokeMembers is doing differently?
I seem to recall a discussion a while back that InvokeMember – being such a jack of all trades method – is slower than the direct MemberInfo access which is why I originally switched to using the MemberInfo structures and their Get and Set methods to set these values.
Because of this issue I decided to backfit my utility routines including the nested ones at least for now. Here’s an example of the nested version of GetPropertyEx() which allows to get properties using ‘.’ syntax (like Invoice object with a property of "Customer.Address.Street").
public static object GetPropertyEx(object Parent, string Property)
{
MemberInfo Member = null;
Type Type = Parent.GetType();
int lnAt = Property.IndexOf(".");
if ( lnAt < 0)
{
if (Property == "this" || Property == "me")
return Parent;
// *** Get the member
return Parent.GetType().InvokeMember(Property,
wwUtils.MemberAccess | BindingFlags.GetProperty | BindingFlags.GetField,
null, Parent,null);
}
// *** Walk the . syntax - split into current object (Main) and parsed objects (Subs)
string Main = Property.Substring(0,lnAt);
string Subs = Property.Substring(lnAt+1);
object Sub = Parent.GetType().InvokeMember(Main,
wwUtils.MemberAccess | BindingFlags.GetProperty | BindingFlags.GetField,null,
Parent,null);
}
// *** Recurse further into the sub-properties (Subs)
return wwUtils.GetPropertyEx(Sub,Subs);
}
For this situation using InvokeMember may actually be more convenient anyway as you can use GetProperty and GetField as the flag in one go.
For now at least if you want to be sure, InvokeMember seems like a more consistent solution.
Other Posts you might also like