我有一个第三方库,它使用反射设置给定的对象属性,如下所示。 (这是简化版)
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<>).MakeGenericType(obj.GetType())
等于int?
但Activator.CreateInstace
返回int
值不是int?
所以这是我的情况......有什么帮助吗?
答案 0 :(得分:0)
试试这段代码......
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 通过 LukeH
更新: 隐藏基本方法。
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; }
}
}
答案 1 :(得分:0)
这应该有效:
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);
}