Assigning a value to a dynamic type using reflection and bypassing the object cast\box that GetValue returns

I have two objects that have exactly the same properties. Here's an example:

public class Field<T>
{
   public T Value {get;set;}
   // more things
}

public class MainObject
{
   public string MyStr {get;set;}
   public int? MyInt {get;set;}
   public bool? MyBool {get;set;}
}

public class MainObjectField
{
   public Field<string> MyStr {get;set;}
   public Field<int?> MyInt {get;set;}
   public Field<bool?> MyBool {get;set;}
}

I have a task to create an instance of MainObjectField based on xpath instructions that I get from an external source.
I need to fetch the Value from the MainObject's instance as a part of the task.

Since I don't know about the type of the current property in compile type, I'm using a dynamic variable.

Here's a short example (this is NOT how the code looks like in real life - this example if to simplify the post):

MainObject obj = new MainObject
{
    MyBool = true,
    MyInt = 12,
    MyStr = "Example"
};

MainObjectField fieldObj = new MainObjectField();
var myBool = obj.GetType().GetProperty("MyBool").GetValue(obj);
var myInt = obj.GetType().GetProperty("MyInt").GetValue(obj);
var myStr = obj.GetType().GetProperty("MyStr").GetValue(obj);

dynamic fieldBool = Activator.CreateInstance(typeof(Field<bool?>));
dynamic fieldInt = Activator.CreateInstance(typeof(Field<int?>));
dynamic fieldString = Activator.CreateInstance(typeof(Field<string>));

fieldBool.Value = myBool; // exception
fieldInt.Value = myInt; // exception
fieldString.Value = myStr; // exception 

fieldObj.MyBool = fieldBool;
fieldObj.MyInt = fieldInt;
fieldObj.MyStr = fieldString;

Now I'm getting this exception:

Cannot implicitly convert type 'object' to 'bool?'. An explicit conversion exists (are you missing a cast?)

I understand why I'm getting the exception and I'm trying to find a workaround.

I know that the currentField.Value and the val value are suppose to be the same type.

My problem is that using reflection (GetValue returns an object) automatically casts\boxes the value into an object and ruins my plans. I can't cast to the "correct" value since I know the types only in runtime.

How can I work this around?

Jon Skeet
people
quotationmark

The problem is that the binder will use the static type of the value you're trying to assign to the property - whereas you want to do this dynamically. All you need to do is change the variables to be of type dynamic and it works:

dynamic myBool = obj.GetType().GetProperty("MyBool").GetValue(obj);
dynamic myInt = obj.GetType().GetProperty("MyInt").GetValue(obj);
dynamic myStr = obj.GetType().GetProperty("MyStr").GetValue(obj);

Basically, dynamic typing will work dynamically with any expressions with a compile-time type of dynamic, but will use the compile-time type of any other expressions when performing that binding.

people

See more on this question at Stackoverflow