/// <summary> /// Accessing a member of a class. The translation is a little tricky. For example: /// arr.jets - don't translate that! /// arr.jets[0].member - do translate that /// [Where jets is a grouped variable] /// /// arr.mc.all_data[0] - translate this when "mc" is a rename, and all_data is a leaf. /// /// arr.jets[0].muonindex.pt - translate that to the muon array /// arr.jets[0].muonsindex[0].pt - translate to the first index of the muon array. /// </summary> /// <param name="expression"></param> /// <returns></returns> protected override Expression VisitMember(MemberExpression expression) { /// /// If this is a bare array that is connected to the main object, then we want /// to not translate this. It will be delt with further above us. /// if (expression.IsRootObjectArrayReference()) return expression; /// /// If this is an object member on a sub-query expression, then it is too early for /// us to look at it. It will come back through here when it gets translated by /// lower level loop unroller code. /// if (expression.Expression is Remotion.Linq.Clauses.Expressions.SubQueryExpression) return expression; /// /// See if the source has a "translated-to" class on it? /// var attr = expression.Expression.Type.TypeHasAttribute<TranslateToClassAttribute>(); if (attr != null) { return RecodeClass(expression, attr); } /// /// Ok, next see if this is an array recoding /// var attrV = expression.Member.TypeHasAttribute<TTreeVariableGroupingAttribute>(); if (attrV != null) { /// /// Sometimes we are deep in the middle of a lambda translation, or similar. In that case, /// we may not be able to walk all the way back. There is a pattern we can detect, however. /// if (expression.Expression is ParameterExpression) return expression; // // If we are looking at a [subqueryexpression].[grouping-obj].[member], which below should be translating // soem how, we need to wait until the subqueryexpression has been totally translated. Which will happen // later on, and then come back through here. // if (expression.Expression is MemberExpression) { var mbaccess = expression.Expression as MemberExpression; if (mbaccess is MemberExpression) { if (mbaccess.Expression is SubQueryExpression) return expression; } } /// /// Regular array recoding - so this is at the top level and is the most /// common kind /// var recodedExpression = RecodeArrayGrouping(expression); if (recodedExpression != null) return recodedExpression; /// /// The only other possibility is if this is in another object that /// we can decode as an array reference. In short - this guy is a /// pointer from another guy to this guy. /// var recoded = RecodeArrayPointer(expression); if (recoded != null) return recoded; /// /// If this has an recode attribute, but we can't do it. Fail! /// throw new NotImplementedException("Member '" + expression.Member.Name + "' is marked for array recoding, but we can't figure out what to do."); } /// /// Hopefully the default behavior is the right thing to do here! /// return base.VisitMember(expression); }