.NET Reflection: Dynamically Cast object at runtime

Steve Endow
Steve Endow used Ask the Experts™
on
I am using .NET Reflection to read fields on an application window.  The Dynamics GP ERP application I'm working with uses proprietary object types, so my reflection code is casting the fields in order to read them.

This is code that successfully reads the value of a window field of type string:

field1Value = ((Microsoft.Dexterity.Bridge.FieldWithEvents<string>)dynamicsWindowType.GetProperty(windowField1).GetValue(dynamicsWindow, null)).Value;

Open in new window


Note the cast to the FieldWithEvents<string> data type.  This allows me to store the field value into a .NET string.

This line of code works fine on string fields, but does not work on other field types, such as Int or Decimal.  For each data type, I would need to use a different cast, like so:

Microsoft.Dexterity.Bridge.FieldWithEvents<int>
Microsoft.Dexterity.Bridge.FieldWithEvents<decimal>


I would like to use reflection to get the field type at runtime and cast the field value so that I don't have to hard code the field type as string, decimal, int, etc.

For example, something like this pseudo code, where genericType would be the type of the field being read:

field1Value = ((Microsoft.Dexterity.Bridge.FieldWithEvents<genericType>)dynamicsWindowType.GetProperty(windowField1).GetValue(dynamicsWindow, null)).Value;

Open in new window


or perhaps

field1Value = ((genericType)dynamicsWindowType.GetProperty(windowField1).GetValue(dynamicsWindow, null)).Value;

Open in new window



I've looked into Generic Types, but I am not sure how to use them in this scenario.  I've tried variations like this:

Type propertyType = dynamicsWindowType.GetProperty(windowField1).PropertyType;
var gpFieldPropertyType = typeof(Microsoft.Dexterity.Bridge.FieldWithEvents<>);
var specificGPFieldType = gpFieldPropertyType.MakeGenericType(propertyType);
                    
field1Value = ((Microsoft.Dexterity.Bridge.FieldWithEvents<specificGPFieldType>)dynamicsWindowType.GetProperty(windowField1).GetValue(dynamicsWindow, null)).Value;

Open in new window


As well as thise:

field1Value = ((specificGPFieldType)dynamicsWindowType.GetProperty(windowField1).GetValue(dynamicsWindow, null)).Value;

Open in new window



The cast always gives an error of:   'specificGPFieldType' is a variable but is used like a type.

How do I replace "string" with the reflected type of the field I'm reading?  Or how do I replace Microsoft.Dexterity.Bridge.FieldWithEvents<string> with a Type that will allow me to cast the field value?

Or can I somehow get rid of the cast of FieldWithEvents entirely?  I would be happy if I could convert any field value to a string.


Here is some info on the string version of the field type, in case it is helpful:

]"}
    Assembly: {Microsoft.Dexterity.Bridge, Version=18.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
    AssemblyQualifiedName: "Microsoft.Dexterity.Bridge.FieldWithEvents`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Microsoft.Dexterity.Bridge, Version=18.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Attributes: Public | BeforeFieldInit
    BaseType: {Name = "Field`1" FullName = "Microsoft.Dexterity.Bridge.Field`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}
    ContainsGenericParameters: false
    DeclaringType: null
    FullName: "Microsoft.Dexterity.Bridge.FieldWithEvents`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
    GUID: {39c86371-2ba3-3aa2-bb52-a5c94d6d200c}
    GenericTypeArguments: {System.Type[1]}
    GenericTypeParameters: {System.Type[0]}
    HasElementType: false
    ImplementedInterfaces: {System.Type[2]}
    IsAbstract: false
    IsAnsiClass: true
    IsArray: false
    IsClass: true
    IsConstructedGenericType: true
    IsGenericParameter: false
    IsGenericType: true
    IsGenericTypeDefinition: false

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Kyle AbrahamsSenior .Net Developer

Commented:
Can't you just make it a string and then parse it?

EG:
string tempNum = 0; //<REPLACE with string get>
int realNum;

if (!int.TryParse(tempNum, out realNum))
// something went wrong

Open in new window


There's also  a more elegant way here:
  https://stackoverflow.com/questions/1196991/get-property-value-from-string-using-reflection-in-c-sharp

Author

Commented:
Hi Kyle,

Thanks for the note.  For the time being, I've done something like that--I have a series of Try / Catch blocks for each data type cast.

I was just hoping for something a little more elegant that could detect the field type via reflection.


try
                {
                    fieldValue = ((Microsoft.Dexterity.Bridge.FieldWithEvents<string>)dynamicsWindowType.GetProperty(windowField).GetValue(dynamicsWindow, null)).Value.ToString();
                    return fieldValue;
                }
                catch (Exception)
                { }

                try
                {
                    fieldValue = ((Microsoft.Dexterity.Bridge.FieldWithEvents<int>)dynamicsWindowType.GetProperty(windowField).GetValue(dynamicsWindow, null)).Value.ToString();
                    return fieldValue;
                }
                catch (Exception)
                { }

Open in new window

Senior .Net Developer
Commented:
https://docs.microsoft.com/en-us/dotnet/api/system.reflection.fieldinfo?view=netframework-4.8

You can use a fieldInfo (or propertyInfo) to determine the type.

See the stack overflow link - I think the GetPropValue will be helpful to you; kinda close to what you're looking for.

Can always surround getPropValue in a try/catch and throw an invalid cast or handle the error differently.

Author

Commented:
Thanks.  I'll give that a try if I can get a chance to work on it again.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial