2012-05-29 59 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

相关问题