本文介绍了防爆pressionTree重写 - 参数'X'的范围并不的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 如果我在以下几个code任何错误/输入错误,请不要irrate,只是下降的注释就在这里,我会立即修复 - 谢谢的重新映射防爆pression&LT; TDelegate&GT; 从一个 EntityA 到 EntityB 。我怀疑这种事情以前也做过,但我还没有发现什么特别有用的链接,以便随时给我指出了正确的方向。I suspect this kind of thing has been done before but I haven't found any particularly useful links so feel free to point me in the right direction.我至今是一个选择的类相结合,允许进行实体成员之间在给定的两个类创建映射。作为一个例子,在表面的API可能具有以下签名:What I have so far is a selection of classes that combine to allow for mappings to be created between Entity Members on two given classes. As an example, the surface API might have the following signature:public void AddMemberBinding<TEntityA, TEntityB, TMember>(Func<TEntityA, TMember> entityAMemberSelector, Func<TEntityB, TMember> entityBMemberSelector){ // does some magic, eventually storing the necessary MemberInfo details required to // "remap" MemberExpressions (MemberAccess) from TEntityA to TEntityB}由于以下类... Given the following classes...public class EntityA{ public long Id { get; set; } public string Name { get; set ;}}public class EntityB{ public long MyId { get; set; } public string MyName { get; set; }}您将能够与沿... public static void AddBindings(){ AddMemberBinding((EntityA n) => n.Id, (EntityB n) => n.MyId); AddMemberBinding((EntityA n) => n.Name, (EntityB n) => n.MyName);}在我的情况,我有 Assembly1 ,知道什么 EntityA 是的,但不知道 EntityB 。我有 Assembly2 这知道这两个 EntityA 和 EntityB 是,并且是可见的 Assembly1 。 Assembly2 提供了一种 Assembly1 这可能如下所示:In my case, I have Assembly1 that knows what EntityA is, but does not know EntityB. I have Assembly2 which knows what both EntityA and EntityB are, and is visible to Assembly1. Assembly2 provides a method to Assembly1 which might look as follows:public static IEnumerable<EntityA> GetData<TResult>(Expression<Func<EntityA, bool>> criteria, Expression<Func<EntityA, TResult>> selector){ // EntityB's are stored in a database, I could do one of two things here... // 1) Return all EntitieB's and then apply criteria and selector through the IEnumerable extensions // this would be sub-optimal - particularly if there are millions of EntityB's! // 2) "Transmute" (for lack of a better word) the expressions provided, using the keymappings // specified earlier, to derive expressions that can be passed through to the QueryableProvider // ... as you might have guessed, I opted for #2}我使用的防爆pressionTree游客,用下面的覆盖的方法:I'm using a derived version of the ExpressionTree Visitor, with the following overridden methods:protected override Expression VisitLambda(LambdaExpression lambda){ Type targetParameterType = lambda.Parameters[0].Type; Type targetExpressionType = lambda.Type; If (lambda.Parameters.Count = 1 && lambda.Parameters(0).Type == EntityA) { targetParameterType = EntityB; // the `GetResultType` method called gets the TResult type from Func<T, TResult> Type targetExpressionResultType = GetResultType(lambda); targetExpressionType = gettype(Func<EntityB, targetExpressionResultType>) } // this is probably wrong, but maintains the current (last) parameter instance // I started doing this after reading about a similar issue to mine found: // http://stackoverflow.com/questions/411738/expression-or-the-parameter-item-is-not-in-scope this.CurrentLambdaParameters = lambda.Parameters.Select(x => Expression.Parameter(targetParameterType, x.Name)); Expression body = this.Visit(lambda.Body); If (body != lambda.Body) { return Expression.Lambda(targetExpressionType, body, this.CurrentLambdaParameters); } return lambda;}protected override Expression VisitMemberAccess(MemberExpression m){ // at this point I go off and look at key mappings, fetch the mapping required, etc // the entity I retrieve has a `TargetMemberInfo` property which is a `MemberInfo` for the // member on the target entity - speaks for itself I guess... return Expression.MakeMemberAccess(this.CurrentParameters.Single(), myMappingClassThing.TargetMemberInfo);}问题与所有的说和做的,当我在code与一个测试用例跑,我得到错误的标题...我可以看到它是从描述一个参数的问题,但看了关于一个类似的问题我希望我的ParameterEx pression同一个实例固定链接 - 曾使用我修改根拉姆达EX pression时创建的参数占了 VisitMemberAccess 法问题问题的问题,我觉得呢?The ProblemWith all that said and done, when I run through the code with a test case, I get the error in the title... I can see it's a parameter issue from the description, but having read about a similiar issue I had hoped I had accounted for the problem in the VisitMemberAccess method by using the parameter I created when modifying the root lambda expression - same instance of ParameterExpression fixed the linked questions problem I think?看来我不明白这个过程的一部分非常好。现在的问题是,在这里我做错什么了!?这是什么,我需要范围做这些ParameterEx pressions他们是?It seems I didn't understand that part of the process very well. The question is, where did I go wrong!? What is it I need to do with these ParameterExpressions for them to be ""in scope""?在此先感谢您的回答,如果你读到这里,荣誉给你!Thanks in advance for your answers, and if you read this far, kudos to you!!推荐答案虽然找过Jon's显着similiar问题和重构纳入了几个他的做法我preferred我自己的实现,我偶然发现了答案。我注意到 VisitParameter 从来没有所谓,因为它的原因是,我重写 VisitMemberAccess 通过前停止递归pression树。Whilst looking over Jon's remarkably similiar question and refactoring to incorporate a couple of his practices I preferred to my own implementation, I stumbled across the answer. I noticed that VisitParameter was never called, the reason for which is that my override of VisitMemberAccess discontinued the recursion through the expression tree.它应该看起来像(使用不同的过载):It should have looked like (using a different overload):protected override Expression VisitMemberAccess(MemberExpression m) { return Expression.MakeMemberAccess(Visit(m.Expression), myMappingClassThing.TargetMemberInfo); } 再加上确保你没有创建相同的参数和多个实例一切插槽在一起很好。Combine that with ensuring you don't create multiple instances of the same parameter and everything slots together nicely.再次感谢乔恩! =) 这篇关于防爆pressionTree重写 - 参数'X'的范围并不的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 11-03 14:53