【问题标题】:Nullable problems with Activator.CreateInstance and Convert.ChangeTypeActivator.CreateInstance 和 Convert.ChangeType 的可空问题
【发布时间】:2013-04-25 13:48:03
【问题描述】:

我有一个第三方库,它使用反射设置给定的对象属性,如下所示。 (这是简化版)

public void Set(object obj, string prop, object value) {
    var propInf = obj.GetType().GetProperty(prop);
    value = Convert.ChangeType(value, propInf.PropertyType);
    propInf.SetValue(obj, value, null);
}

我们有一个可以为空属性的类

class Test
{
    public int? X { get; set; }
}

当我编写以下代码时,它说它无法将int 转换为int?

var t = new Test();
Set(t, "X", 1);

由于 Nullable 没有实现 IConvertible 它是有意义的。然后我决定编写一个返回给定值类型对象的可为空版本的方法。

public object MakeNullable(object obj) {
    if(obj == null || !obj.GetType().IsValueType)
        throw new Exception("obj must be value type!");

    return Activator.CreateInstance(
        typeof(Nullable<>).MakeGenericType(obj.GetType()), 
        new[] { obj });
}

我希望如下使用这个方法。

var t = new Test();
Set(t, "X", MakeNullable(1));

但它仍然说它无法将int 转换为int?。当我调试typeof(Nullable&lt;&gt;).MakeGenericType(obj.GetType()) 等于int?Activator.CreateInstace 返回int 值而不是int?

所以这是我的情况...有什么帮助吗?

【问题讨论】:

  • 您找到解决方案了吗?我一直在玩 Activator 等大约一个小时,但没有任何运气。它总是返回内存中的底层类型。

标签: c# reflection type-conversion nullable activator


【解决方案1】:

这应该可行:

public static object ChangeType(object value, Type conversionType)
{
   if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition() == typeof(Nullable<>))
   {
       if (value == null)
           return null;
       var nullableConverter = new NullableConverter(conversionType);
       conversionType = nullableConverter.UnderlyingType;
    }
    return Convert.ChangeType(value, conversionType);
 }

【讨论】:

    【解决方案2】:

    试试这个代码...

    public void Set(object obj, string prop, object value)
          {
              //var propInf = obj.GetType().GetProperty(prop);
              //value = Convert.ChangeType(value, propInf.PropertyType);
              //propInf.SetValue(obj, value, null);
              var property = obj.GetType().GetProperty(prop);
              if (property != null)
              {
                  Type t = Nullable.GetUnderlyingType(property.PropertyType)
                               ?? property.PropertyType;
    
                  object safeValue = (value == null) ? null
                                                     : Convert.ChangeType(value, t);
    
                  property.SetValue(obj, safeValue, null);
              }
          }
    

    从这里 Convert.ChangeType() fails on Nullable Types 经过 卢克H

    更新: 隐藏基础方法。

    namespace ConsoleApplication2
    {
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    internal class Program
    {
        private static void Main(string[] args)
        {
            EnterPoint t = new EnterPoint();
            t.BeginProcess();
        }
    }
    
    public class EnterPoint
    {
        public void BeginProcess()
        {
            var t = new Test(); //Object
    
            try
            {
                baseDllMethod m = new baseDllMethod(); //Your DLL
                m.Set(t, "X", 1); //Problem Method, this give you error
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR EN DLL METHOD");    
            }
    
    
            xyz_D der = new xyz_D(); //Derivated method
            der.Set(t, "X", 1) ; //HIDE BASE METHOD
        }
    }
    
    public class baseDllMethod //YOUR DLL HERE
    {
        public void Set(object obj, string prop, object value)
        {
            var propInf = obj.GetType().GetProperty(prop);
            value = Convert.ChangeType(value, propInf.PropertyType);
            propInf.SetValue(obj, value, null);
        }
    }
    
    public class xyz_D : baseDllMethod //Inherits
    {
        public new void Set(object obj, string prop, object value) //Hide base method
        {
            var property = obj.GetType().GetProperty(prop);
            if (property != null)
            {
                Type t = Nullable.GetUnderlyingType(property.PropertyType)
                             ?? property.PropertyType;
    
                object safeValue = (value == null) ? null
                                                   : Convert.ChangeType(value, t);
    
                property.SetValue(obj, safeValue, null);
            }
        }
    }
    
    public class Test //Your Object
    {
        public int? X { get; set; }
    }
    

    }

    【讨论】:

    • 我知道,但是 Set 方法在我无法修改的库中。另外,不幸的是,事情并没有这么简单。
    猜你喜欢
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多