'casting' with reflection

前端 未结 6 1800
面向向阳花
面向向阳花 2020-11-30 21:47

Consider the following sample code:

class SampleClass
{
    public long SomeProperty { get; set; }
}

public void SetValue(SampleClass instance, decimal valu         


        
相关标签:
6条回答
  • 2020-11-30 22:18

    When the Type is a Nullable Guid then none of the above proposed solutions work. Invalid cast from 'System.DBNull' to 'System.Guid' exception is thrown at Convert.ChangeType

    To fix that change to:

    var convertedValue = value == System.DBNull.Value ? null : Convert.ChangeType(value, targetType);
    
    0 讨论(0)
  • 2020-11-30 22:21

    Contributing to jeroenh's answer, I would add that Convert.ChangeType crashes with a null value, so the line for getting the converted value should be:

    var convertedValue = value == null ? null : Convert.ChangeType(value, targetType);
    
    0 讨论(0)
  • 2020-11-30 22:26

    The answer by Thomas is right, but I thought I would add my finding that Convert.ChangeType does not handle conversion to nullable types. To handle nullable types, I used the following code:

    void SetValue(PropertyInfo info, object instance, object value)
    {
        var targetType = info.PropertyType.IsNullableType() 
             ? Nullable.GetUnderlyingType(info.PropertyType) 
             : info.PropertyType; 
        var convertedValue = Convert.ChangeType(value, targetType);
    
        info.SetValue(instance, convertedValue, null);
    }
    

    This code makes use of the following extension method:

    public static class TypeExtensions
    {
      public static bool IsNullableType(this Type type)
      {
        return type.IsGenericType 
        && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>));
      }
    
    0 讨论(0)
  • 2020-11-30 22:29

    This is a very old question but I thought I'd chime in for ASP.NET Core Googlers.

    In ASP.NET Core, .IsNullableType() is protected (amongst other changes) so the code is a tad different. Here's @jeroenh's answer modified to work in ASP.NET Core:

    void SetValue(PropertyInfo info, object instance, object value)
    {
        Type proptype = info.PropertyType;
        if (proptype.IsGenericType && proptype.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
        {
            proptype = new NullableConverter(info.PropertyType).UnderlyingType;
        }
    
        var convertedValue = Convert.ChangeType(value, proptype);
        info.SetValue(instance, convertedValue);
    }
    
    0 讨论(0)
  • 2020-11-30 22:30
    void SetValue(PropertyInfo info, object instance, object value)
    {
        info.SetValue(instance, Convert.ChangeType(value, info.PropertyType));
    }
    
    0 讨论(0)
  • 2020-11-30 22:31

    Thomas answer only works for types that implement IConvertible interface:

    For the conversion to succeed, value must implement the IConvertible interface, because the method simply wraps a call to an appropriate IConvertible method. The method requires that conversion of value to conversionType be supported.

    This code compile a linq expression that does the unboxing (if needed) and the conversion:

        public static object Cast(this Type Type, object data)
        {
            var DataParam = Expression.Parameter(typeof(object), "data");
            var Body = Expression.Block(Expression.Convert(Expression.Convert(DataParam, data.GetType()), Type));
    
            var Run = Expression.Lambda(Body, DataParam).Compile();
            var ret = Run.DynamicInvoke(data);
            return ret;
        }
    

    The resulting lambda expression equals to (TOut)(TIn)Data where TIn is the type of the original data and TOut is the given type

    0 讨论(0)
提交回复
热议问题