Ben ifade ağacı oluşturma ve başka lambda bir lambda oluşturmak ve bir sınıfta bir tane iç depolamak ve ifade ağacında bu sınıf eklemek gerekir bir durum var - Dış lambda iç lambda derlemek. Bu benim yapmaya çalıştığım şeyin basit bir örnek (bu kod derleme değil):İfade ağacı - kapsam çözünürlük
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace SimpleTest {
public class LambdaWrapper {
private Delegate compiledLambda;
public LambdaWrapper(Delegate compiledLambda) {
this.compiledLambda = compiledLambda;
}
public dynamic Execute() {
return compiledLambda.DynamicInvoke();
}
}
public class ForSO {
public ParameterExpression Param;
public LambdaExpression GetOuterLambda() {
IList<Expression> lambdaBody = new List<Expression>();
Param = Expression.Parameter(typeof(object), "Param");
lambdaBody.Add(Expression.Assign(
Param,
Expression.Constant("Value of 'param' valiable"))
);
lambdaBody.Add(Expression.Call(
null,
typeof(ForSO).GetMethod("Write"),
Param)
);
Delegate compiledInnerLambda = GetInnerLambda().Compile();
LambdaWrapper wrapper = new LambdaWrapper(compiledInnerLambda);
lambdaBody.Add(Expression.Constant(wrapper));
//lambdaBody.Add(GetInnerLambda());
return Expression.Lambda(
Expression.Block(
new ParameterExpression[] { Param },
lambdaBody));
}
public LambdaExpression GetInnerLambda() {
return Expression.Lambda(
Expression.Block(
Expression.Call(null,
typeof(ForSO).GetMethod("Write"),
Expression.Constant("Inner lambda start")),
Expression.Call(null,
typeof(ForSO).GetMethod("Write"),
Param),
Expression.Call(null,
typeof(ForSO).GetMethod("Write"),
Expression.Constant("Inner lambda end"))
)
);
}
public static void Write(object toWrite) {
Console.WriteLine(toWrite);
}
public static void Main(string[] args) {
ForSO so = new ForSO();
LambdaWrapper wrapper = so.GetOuterLambda().Compile()
.DynamicInvoke() as LambdaWrapper;
wrapper.Execute();
//(so.GetOuterLambda().Compile().DynamicInvoke() as Delegate).DynamicInvoke();
}
}
}
Sorun GetOuterLambda
yöntemde GetInnerLambda().Compile()
çizgidedir. Tek bir çözümün farkındayım - kodun bir kısmı yorumlanmıştır. Bunun üzerine, her şey iyi çalışıyor, ama değil ifadesi alt ağacı (o LambdaWrapper iç lambda alt ağacı saklamak için Tamam olabilir, ve daha sonra derlemek, ama aynı sorun occures) dönüş değeri olarak bir sarmalayıcı gerekir. Ben alıyorum
Hata Unhandled Exception: System.InvalidOperationException: variable 'Param' of type 'System.Object' referenced from scope '', but it is not defined
olduğunu.
I iç lambdanın kodu derler değişkenlerin blok Param
eklemek ancak param dış lambda atanan değer değildir (ve mantıklı) ise.
Bu nasıl çözülebilir? senin LambdaWrapper
yılında
public LambdaExpression GetInnerLambda()
{
var param = Expression.Parameter(typeof(object));
return Expression.Lambda(
Expression.Block(
Expression.Call(null,
typeof(ForSO).GetMethod("Write"),
Expression.Constant("Inner lambda start")),
Expression.Call(null,
typeof(ForSO).GetMethod("Write"),
param),
Expression.Call(null,
typeof(ForSO).GetMethod("Write"),
Expression.Constant("Inner lambda end"))
),
param
);
}
Sonra parametrenin değerini depolamak: Eğer iç lambda ifadede bir sabit değer olarak Param
kullanamazsınız çünkü
teşekkürler.Bu yaklaşım hakkında sevmediğim şey, bu lambdaların gerçek fonksiyonlar olması ve parametrelerine sahip olabilmeleri (söz konusu parçayı ben dahil etmediğim için söz konusu kısmı eklemedim) ve Param sadece Değişken ihtiyacım var (bunların birçoğu olabilir), bu yüzden kapsamlamanın çözülmesi için yapay parametrelerin çok zarif bir çözüm olduğunu düşünmüyorum. –
Güncelleme yanıtı sadece benim için çalışabilir, ancak çalışma bilgisayarıma döndüğümde kontrol etmem gerekecek. Teşekkürler ... –
Bunun benim için çalıştığını kontrol ettim. Neredeyse :). Bir adım daha ileri sürdüm ve LambdaWrapper örneğini oluşturmak için DynamicExpression'u yarattım. Bağlayıcılar yaratmam gerekti, bu yüzden bu ruhsallık daha çok iş gerektiriyor, ancak zaten onları ana projemde zaten yaptım. Bu sorunu çözmek için gösterdiğiniz ilgi için teşekkürler :) –