简体   繁体   English

Activator.CreateInstance和Convert.ChangeType的空问题

[英]Nullable problems with Activator.CreateInstance and Convert.ChangeType

I have a third party library which sets a given objects property using reflection as follows. 我有一个第三方库,它使用反射如下设置给定的对象属性。 (This is the simplified version) (这是简化版)

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);
}

And We have class with a nullable property 而且我们有一个带有可空属性的类

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

When I write the following code, it says it cannot convert int to int? 当我编写以下代码时,它说不能将int转换为int?

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

Since Nullable does not implement IConvertible it makes sense. 由于Nullable没有实现IConvertible,所以这很有意义。 Then I decided to write a method which returns the nullable version of a given value typed object. 然后,我决定编写一个方法,该方法返回给定值类型对象的可空版本。

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 });
}

I hoped to use this method as follows. 我希望按如下方式使用此方法。

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

But it still says it cannot convert int to int? 但是它仍然说不能将int转换为int? . When I debug typeof(Nullable<>).MakeGenericType(obj.GetType()) equals int? 当我调试typeof(Nullable<>).MakeGenericType(obj.GetType())等于int? but Activator.CreateInstace returns an int value not int? 但是Activator.CreateInstace返回的是int值而不是int?

So this is my case... Any help? 这就是我的情况...有什么帮助吗?

Try this code... 试试这个代码...

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);
          }
      }

from here Convert.ChangeType() fails on Nullable Types by LukeH 从这里,LukeH的Nullable Types上的Convert.ChangeType()失败

UPDATE : Hide base method. 更新:隐藏基本方法。

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; }
}

} }

This should work: 这应该工作:

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);
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM