如何创建Nullable <t>的实例?</t>

时间:2014-02-25 07:32:56

标签: c# linq generics reflection

假设我们有两个类:

public class ParentEntity
{
    public ChildEntity Child { get; set; }
}

public class ChildEntity
{
    public byte? NullableValue { get; set; }
    public byte Value { get; set; }
}

任务是在linq表达式中表达以下代码:

parent.Child == null ? null : parent.Child.NullableValue

为此,我尝试使用以下代码:

public static Expression GetCondition<TParent, TChild, TChildKey>(
                              Expression<Func<TParent, TChild>> pe, 
                              Expression<Func<TChild, TChildKey>> ce)
{
    var test = Expression.Equal(pe.Body, Expression.Constant(null));

    var ifTrue = Expression.Constant(Activator.CreateInstance<TChildKey>());
    var ifFalse = Expression.Property(pe.Body, 
                                      (ce.Body as MemberExpression).Member.Name);
    return Expression.Condition(test, ifTrue, ifFalse);
}

使用

运行此代码
Expression<Func<ParentEntity, ChildEntity>> pe = n => n.Child;    

GetCondition(pe, n => n.Value);         // ok
GetCondition(pe, n => n.NullableValue); // throws an ArgumentException

在最后一行(ArgumentException的return语句处)抛出GetCondition,表示参数类型不匹配。

分析了这段代码后,我发现当Activator.CreateInstance<TChildKey>()object时,TChildKey会返回TChildKey,而不是System.Nullable<T>,即ifTrue.Typeobject,而我预计它是System.Nullable<byte>

SO: Creating a nullable object via Activator.CreateInstance returns null指向Reflection and Nullable

讨论了这个问题

但这些都没有提出任何解决问题的方法。

有没有办法创建一个System.Nullable<T>类型的实例,其值为null? 或者也许有其他方式表达原始条件表达式?

3 个答案:

答案 0 :(得分:2)

您应该尝试Expression.New

var ifTrue = Expression.New(typeof(Nullable<int>));

答案 1 :(得分:0)

这对你有用吗<​​/ p>

    public static Expression GetCondition<TParent, TChild, TChildKey>(
                          Expression<Func<TParent, TChild>> pe,
                          Expression<Func<TChild, TChildKey>> ce)
    {
        var test = Expression.Equal(pe.Body, Expression.Constant(null));

        ConstantExpression ifTrue;
        Type type = typeof(TChildKey);
        // check if it is a nullable type
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>))
        {
            ifTrue = Expression.Constant(default(TChildKey));
        }
        else
        {
            ifTrue = Expression.Constant(   Activator.CreateInstance<TChildKey>());
        }

        var ifFalse = Expression.Property(pe.Body, (ce.Body as MemberExpression).Member.Name);

        return Expression.Condition(test, ifFalse, ifFalse);
    }

答案 2 :(得分:0)

另一种选择是使用两个参数函数重载明确指定Expression.Constant创建的常量类型。

var ifTrue = Expression.Constant(Activator.CreateInstance<TChildKey>(), typeof(TChildKey));

Nullable<>需要一些非常小心的处理,特别是在空值之外。明确是有帮助的,并且在做标准之外的任何事情时经常是必要的。