2012-05-29 56 views
4

我剛碰到涉及Expressions的問題。如何從無類型的表達式返回到鍵入的表達式?

在我class<T>有一個字段

Dictionary<Expression, ProjectedCollection> mCache; 

其中兩個ExpressionProjectedCollection不能被指定爲Expression<T, S>ProjectedCollection<S>因爲S會在運行時是不同的東西:

void AddSomething<S>(Expression<Func<T, S>> projection) 
{ 
    if (!mCache.ContainsKey(projection)) 
    { 
    var runnable = projection.Compile(); 
    var allProjected = from elm in mList 
         select runnable(elm); 

    mCache.Add(projection, new ProjectedCollection<S>(allProjected)); 
    } 
} 

現在我在某個地方不知道S,我想要迭代緩存中的所有內容並將表達式應用於新事物。

foreach (KeyValuePair<Expression, ProjectedCollection> keyValuePair in mCache) 
{ 
    // Want something like 
    var func = keyValuePair.Key.Compile(); 
    keyValuePair.Value.SignalAdd(func(newThing)); 
} 

Compile()法不適用於非類型化Expression。如果不知道S,鑄造也是不可能的。

有沒有人有一個想法如何解決這個問題?

+0

您的方法存在問題...'Expression'不會覆蓋'Equals'和'GetHashCode',因此將其用作字典鍵將不起作用。兩個相同的表達式不會被認爲是相等的...... –

+1

順便說一句,'Compile'方法在'LambdaExpression'中可用,它是'Expression '的基類。但它返回一個無類型委託... –

+0

@ThomasLevesque:這是由自定義的'IEqualityComparer'解決。 – primfaktor

回答

2

將其轉換爲LambdaExpression,然後調用Compile。它將返回一個無類型的委託。你可以...

  • ...施放此代表對功能/動作類型
  • 之一...使用反射
  • 檢查其結構...使用Delegate.DynamicInvoke稱之爲
+0

由於缺少'S',投射代表也是不可能的。但是,將「LambdaExpression」與「DynamicInvoke」結合使用可以完成這項工作。謝謝! – primfaktor

相關問題