Convert to a Type on the fly in C#.NET
Asked Answered
L

5

26

Alternative Title: Dynamically convert to a type at runtime.

I want to to convert an Object to a type that will be assigned at runtime.

For example, assume that I have a function that assigns a string value(from a TextBox or Dropdownlist) to an Object.Property.

How would I convert the value to proper type? For instance, it could be an integer, string, or enum.

Public void Foo(object obj,string propertyName,object value)
{
  //Getting type of the property og object.
  Type t= obj.GetType().GetProperty(propName).PropertyType;

  //Now Setting the property to the value .
  //But it raise an error,because sometimes type is int and value is "2"
  //or type is enum (e.a: Gender.Male) and value is "Male"
  //Suppose that always the cast is valid("2" can be converted to int 2)

  obj.GetType().GetProperty(propName).SetValue(obj, value, null);
}
Locomotive answered 30/9, 2011 at 21:15 Comment(3)
can you give a example where this would be used? If you don't know the concrete type why would you need to cast it? Have you thought going dynamic?Maledict
Do you know what the type is when you pass the argument into the Foo method?Pazice
@JamesJohnson I think you can always find out if you need :-)Folklore
C
47

You need to use the Convert.ChangeType(...) function [note: in the function below, the input propertyValue could just as easily have been of type object ... I just had a string version pre-baked]:

/// <summary>
/// Sets a value in an object, used to hide all the logic that goes into
///     handling this sort of thing, so that is works elegantly in a single line.
/// </summary>
/// <param name="target"></param>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
public static void SetPropertyValueFromString(this object target,               
                              string propertyName, string propertyValue)
{
    PropertyInfo oProp = target.GetType().GetProperty(propertyName);
    Type tProp = oProp.PropertyType;

    //Nullable properties have to be treated differently, since we 
    //  use their underlying property to set the value in the object
    if (tProp.IsGenericType
        && tProp.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    {
        //if it's null, just set the value from the reserved word null, and return
        if (propertyValue == null)
        {
            oProp.SetValue(target, null, null);
            return;
        }

        //Get the underlying type property instead of the nullable generic
        tProp = new NullableConverter(oProp.PropertyType).UnderlyingType;
    }

    //use the converter to get the correct value
    oProp.SetValue(target, Convert.ChangeType(propertyValue, tProp), null);
}
Chloroplast answered 30/9, 2011 at 21:21 Comment(5)
The only downside to this approach is that it won't work on nullable types.Pazice
Just noticed that you do have some logic in there for nullable types.Pazice
Convert.ChangeType() is satisfying although I should do some checking for enums , tnx fordareh.Locomotive
Is there a difference between new NullableConverter(oProp.PropertyType).UnderlyingType and Nullable.GetUnderylingType(oProp.PropertyType)? I assume the latter is just newer.Lacreshalacrimal
@Lacreshalacrimal - It looks like they've both been around since .NET 2.0, but I think you're right to note that the instantiation overhead of the NullableConverter (though minimal) probably isn't necessary in this case. In fact, I wasn't aware of the Nullable.GetUnderylingType method. Thanks for the heads up!Chloroplast
A
2

A universal Type Converter is what you seek !? Not an easy feat..

Try this approach:

Universal Type Converter

You can in NuGet Install-Package UniversalTypeConverter

Also, is using Generics out of the question here? It would facilitate the solution if you know at least the target type of the conversion.

Antaeus answered 30/9, 2011 at 21:20 Comment(0)
B
1

I'm not sure it works, but give it a try:

public static T To<T>(this IConvertible obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

Public void Foo(object obj,string propertyName,object value)
{
    Type t= obj.GetType().GetProperty(propName).PropertyType;
    obj.GetType().GetProperty(propName).SetValue(obj, value.To<t>(), null);
}
Blane answered 30/9, 2011 at 21:23 Comment(3)
It doesn't work, because generic type t in To<t>() must be defined in compile time .Locomotive
@Navid: no, because of the extension method I put at the beginning of my answer. I'm quite sure it will be evaluated at runtime...Blane
I can say for a fact that this does not work and that @Navid is correct. Generic methods need the type to be provided at compile timeHay
P
1

Here's another way you can do it, but I'm not sure

Without support for generic types:

public void Foo(object obj,string propertyName,object value) 
{ 
    //Getting type of the property og object. 
    Type type = obj.GetType().GetProperty(propertyName).PropertyType;

    obj.GetType().GetProperty(propertyName).SetValue(obj, Activator.CreateInstance(type, value), null);
} 

With support for generic types:

public void Foo(object obj,string propertyName,object value) 
{ 
    //Getting type of the property og object. 
    Type type = obj.GetType().GetProperty(propertyName).PropertyType;

    if (type.IsGenericType)
        type = type.GetGenericArguments()[0];

    obj.GetType().GetProperty(propertyName).SetValue(obj, Activator.CreateInstance(type, value), null);
} 
Pazice answered 30/9, 2011 at 21:57 Comment(0)
N
1

I used the Convert function in C#. The way I'm doing my conversion is using reflection.:

Type type = this.myObject.GetType();

if (type.Name == "MyObjectClass") {
var Voucherrequest = (MyObjectClass)Convert.ChangeType(myObject, typeof(MyObjectClass));

This is all assuming you know what type you want to convert into. You can even make a switch and have multiple types you want to reflect too.

Nickolas answered 21/7, 2016 at 17:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.