Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将[TYPE]转换为可空<;[类型]>;在C#中?_C#_.net_Reflection_Nullable_Activator - Fatal编程技术网

如何将[TYPE]转换为可空<;[类型]>;在C#中?

如何将[TYPE]转换为可空<;[类型]>;在C#中?,c#,.net,reflection,nullable,activator,C#,.net,Reflection,Nullable,Activator,问题: 我编写了一个方法,将SQL结果检索为类的列表,而不是数据表。 问题是,数据库中有一个int字段,可以为null 如果我用NULLint点击一行,DataReader返回DbNull.Value,而不是NULL。 因此System.Convert.ChangeType(objVal,fi.FieldType)抛出异常,因为它无法将DbNull转换为int 到目前为止还很糟糕。 当我将objVal与DbNull.Value进行比较时,我认为我已经解决了这个问题,如果是真的,则改为: Syst

问题:

我编写了一个方法,将SQL结果检索为类的列表,而不是数据表。 问题是,数据库中有一个int字段,可以为null

如果我用
NULL
int
点击一行,
DataReader
返回
DbNull.Value
,而不是NULL。 因此
System.Convert.ChangeType(objVal,fi.FieldType)
抛出异常,因为它无法将
DbNull
转换为
int

到目前为止还很糟糕。 当我将
objVal
DbNull.Value
进行比较时,我认为我已经解决了这个问题,如果是真的,则改为:
System.Convert.ChangeType(null,fi.FieldType)

不幸的是,我刚刚意识到,结果的整数类型是0而不是NULL

因此,我刚刚尝试将类中的int类型更改为
Nullable
,但现在我遇到了一个问题,即当值不是
DbNull.value
时,
ChangeType
抛出异常,因为它无法将
int
转换为
Nullable

因此,现在我尝试检测
datareader
返回的对象类型,并将其转换为可为空的值

tTypeForNullable
正确显示为
Nullable
。 但是当我查看结果类型时,我得到:
int

为什么呢?更重要的是:我如何才能正确地做到这一点

请注意,因为type是一个对象,所以我不能使用泛型方法来创建
Nullable

bool bisnull = IsNullable(objVal);
bool bisnullt = IsNullable(fi.FieldType);

if (bisnullt)
{
    Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType());

    //object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal });
    //object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal });
    object result = Activator.CreateInstance(tTypeForNullable, objVal);
    Type tres = result.GetType();
    fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType));
}

请注意,因为类型是一个对象,所以我不能使用泛型方法来创建要装箱的
Nullable

可空值类型的装箱操作的结果永远不会是该类型的装箱值。它是null或不可为null的值类型。有关更多信息,请参阅。

您见过实体框架吗?@Bas:是的,速度太慢了。但比反射快得多,如果你使用AsNoTracking,它的速度几乎和DataReader一样快。我刚刚遇到了同样的问题,我认为在c#中不可能使用反射来设置可为null类型的值。@Quandary:老实说,现在还不清楚你想做什么。是否存在“通过反射设置可为空的字段”的问题?将其与数据库方面等隔离是值得的。真正的问题是System.Convert.ChangeType不适用于可为空的类型。但我刚刚看到int的原始字段实际上是一个varchar。。。这就是为什么皈依是必要的。现在使用nullable,一切正常,如果fi.FieldType是nullable,我可能不会调用convert。@Quandary:我认为这不是你真正的核心问题-你不需要解决这个问题,你需要解决用反射设置字段的问题,对吗?如果
ChangeType
为空时对您没有帮助,请不要使用它。@John Skeet:没有ChangeType,您无法直接将varchar读入int字段,这有点小意思。对于ChangeType,它将NULL映射为0。其思想过程是,使用NULL-able,Convert将NULL设置为NULL。现在我明白了为什么不能这样做了:Convert不能将可为null的类型作为对象返回,因为这将从返回的类型中删除可为null的类型。。。剩下的唯一问题是:这种对象装箱行为有什么意义……这使得不可能对可空类型进行任何转换。也许您应该将您的响应更新为:“这无法完成”@Quandary-只需将整数值存储到可为空的整数变量中即可。
bool bisnull = IsNullable(objVal);
bool bisnullt = IsNullable(fi.FieldType);

if (bisnullt)
{
    Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType());

    //object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal });
    //object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal });
    object result = Activator.CreateInstance(tTypeForNullable, objVal);
    Type tres = result.GetType();
    fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType));
}
public System.Data.IDataReader ExecuteReader(System.Data.IDbCommand cmd)
        {
            System.Data.IDataReader idr = null;

            lock(cmd)
            {
                System.Data.IDbConnection idbc = GetConnection();
                cmd.Connection = idbc;

                if (cmd.Connection.State != System.Data.ConnectionState.Open)
                    cmd.Connection.Open();

                idr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            } // End Lock cmd

            return idr;
        } // End Function ExecuteReader