2014-02-25 62 views
6

假設我們有兩大類:如何創建一個可爲空的實例<T>?

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 

在最後一行(在GetCondition的返回語句中)拋出ArgumentException,表示參數類型不匹配。

在分析這個代碼,我發現,Activator.CreateInstance<TChildKey>()回報object,但不TChildKey,當TChildKeySystem.Nullable<T>,即ifTrue.Typeobject,而我希望它是System.Nullable<byte>

就此問題在SO: Creating a nullable object via Activator.CreateInstance returns null指向討論Reflection and Nullable

但這些都不意味着什麼解決問題。

有沒有辦法創建一個確切System.Nullable<T>類型的實例,其值爲null? 或者也許有其他方式來表達原始條件表達式?

回答

2

你應該嘗試Expression.New

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

哪裏可以深入瞭解這些特點,我想知道!? – horgh

0

將這項工作對你

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

因爲'ifTrue.Type'仍然是'Object' for'default(TChildKey)',所以這不起作用。 – horgh

0

另一種選擇是明確指定正在Expression.Constant使用兩個參數的函數重載創建什麼類型的常量。

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

Nullable<>需要一些非常小心處理,特別是圍繞空。在規範之外做任何事情時,明確是有幫助的,而且往往是必要的。

相關問題