private object CreateExpressionInternal(Expression expression, IEnumerable <ParameterExpression> parameters, IDictionary <string, object> parameterMappings, Type returnType) { var modelFuncVisitor = new ModelFuncExpressionVisitor(); var modelFunc = modelFuncVisitor.Visit(expression); var visitor = new TreeExtensionExpressionVisitor(); visitor.Visit(modelFunc); var collectedParameterInfos = visitor.CollectParameterInfos(); var parameterList = visitor.ListParameters(); var types = new Type[parameterList.Count + 1]; var args = new object[3 * parameterList.Count + 1]; if (parameterMappings == null && modelFuncVisitor.ExtractParameters.Count > 0) { parameterMappings = new Dictionary <string, object>(); } foreach (var ex in modelFuncVisitor.ExtractParameters) { parameterMappings.Add(ex.Parameter.Name, ModelNotifySystem.Instance.CreateExpression(ex.Value, parameters, parameterMappings)); } var expressionLambda = Expression.Lambda(modelFunc, parameterList); var expressionCompiled = expressionLambda.Compile(); args[0] = expressionCompiled; for (int i = 0; i < parameterList.Count; i++) { var parameter = parameterList[i]; types[i] = parameter.Type; args[3 * i + 1] = CreateNotifyValue(parameter.Name, parameterMappings, parameter.Type); TreeExtensionExpressionVisitor.ParameterInfo parInfo; if (collectedParameterInfos.TryGetValue(parameter, out parInfo)) { args[3 * i + 3] = parInfo.Properties; args[3 * i + 2] = parInfo.Anchors; } else { args[3 * i + 3] = null; args[3 * i + 2] = null; } } types[parameterList.Count] = returnType; var treeExtensionCallType = ObservableTreeExtensionCallTypes.Types[types.Length - 2].MakeGenericType(types); var constructor = treeExtensionCallType.GetConstructors()[0]; #if DEBUG if (constructor == null) { System.Diagnostics.Debugger.Break(); } #endif return(constructor.Invoke(args)); }
private object CreateExpressionInternal(Expression expression, IEnumerable <ParameterExpression> parameters, IDictionary <string, object> parameterMappings, Type returnType) { var modelFuncVisitor = new ModelFuncExpressionVisitor(); var modelFunc = modelFuncVisitor.Visit(expression); var promotionVisitor = new PromotionExpressionVisitor(); var promotionExpression = promotionVisitor.Visit(modelFunc); var collectedParameterInfos = promotionVisitor.CollectParameterInfos(); var parametersNew = promotionVisitor.ListParameters(); var newExpression = Expression.Lambda(promotionExpression, parametersNew); var newExpressionCompiled = newExpression.Compile(); var types = new Type[parametersNew.Count + 1]; var args = new object[3 * parametersNew.Count + 1]; args[0] = newExpressionCompiled; if (parameterMappings == null && modelFuncVisitor.ExtractParameters.Count > 0) { parameterMappings = new Dictionary <string, object>(); } foreach (var ex in modelFuncVisitor.ExtractParameters) { parameterMappings.Add(ex.Parameter.Name, ModelNotifySystem.Instance.CreateExpression(ex.Value, parameters, parameterMappings)); } for (int i = 0; i < parametersNew.Count; i++) { var parameter = parametersNew[i]; var extraction = promotionVisitor.ExtractParameters.FirstOrDefault(ex => ex.Parameter == parameter); if (extraction.Parameter == null) { // The parameter is an original parameter args[3 * i + 1] = CreateNotifyValue(parameter.Name, parameterMappings, parameter.Type); types[i] = parameter.Type; } else { var val = extraction.Value; if (!typeof(IModelElement).IsAssignableFrom(val.Type) && !typeof(IEnumerableExpression).IsAssignableFrom(val.Type) && !typeof(INotifyEnumerable).IsAssignableFrom(val.Type)) { throw new NotSupportedException("Currently, only extraction of parameters typed as model elements or notifiable collections is supported."); } args[3 * i + 1] = ModelNotifySystem.Instance.CreateExpression(val, parameters, parameterMappings); types[i] = val.Type; } PromotionExpressionVisitor.ParameterInfo parInfo; if (collectedParameterInfos.TryGetValue(parameter, out parInfo)) { args[3 * i + 2] = parInfo.Properties; args[3 * i + 3] = parInfo.NeedsContainment; } else { args[3 * i + 2] = null; args[3 * i + 3] = false; } } types[types.Length - 1] = returnType; var promotionMethodCallType = promotionMethodCallTypes[types.Length - 2].MakeGenericType(types); var constructor = promotionMethodCallType.GetConstructors()[0]; #if DEBUG if (constructor == null) { System.Diagnostics.Debugger.Break(); } #endif return(constructor.Invoke(args)); }