private List <object>?GetItems(LambdaExpression?filterExpression, MethodCallExpression causeOfException, Expression instanceOfMethodCallExpression) { var instance = ExpressionHelper.EvaluateExpression(instanceOfMethodCallExpression); if (!(instance is IEnumerable enumerable)) { return(null); } var items = new List <object>(); var filter = filterExpression?.Compile(true); foreach (var i in enumerable) { bool AddItem() { items.Add(i); if (items.Count > 10) { return(false); } return(true); } if (filter != null) { var result = (bool)filter.DynamicInvoke(i); if (result) { if (!AddItem()) { break; } } } else { if (!AddItem()) { break; } } } return(items); }
/// <summary> /// 为现有目标对象创建成员 /// </summary> public virtual void CreateMemberAssignementForExistingTarget() { if (PropertiesMapping.Count > 0) { // 用于更改原始表达式的参数。 var paramTarget = Expression.Parameter(TargetType, paramClassSource.Name.Replace("s", "t")); ChangParameterExpressionVisitor visitSource = new ChangParameterExpressionVisitor(paramClassSource); ChangParameterExpressionVisitor visitTarget = new ChangParameterExpressionVisitor(paramTarget); List <Expression> finalAssign = new List <Expression>(); foreach (var item in PropertiesMapping) { var propToAssign = visitTarget.Visit(item.Item2); var assignExpression = visitSource.Visit(item.Item1); Type sourceType = TypeSystem.GetElementType(item.Item2.Type); Type targetType = TypeSystem.GetElementType(item.Item1.Type); if (string.IsNullOrEmpty(item.Item4)) { object defaultValue = MapperHelper.GetDefaultValue(item.Item2.Type); Expression defaultExpression = Expression.Constant(defaultValue, item.Item2.Type); Expression checkIfNull = Expression.NotEqual(assignExpression, defaultExpression); if (item.Item3) { Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression)); finalAssign.Add(setIf); } else { if (!IsListOf(propToAssign.Type)) { finalAssign.Add(Expression.Assign(propToAssign, assignExpression)); } else { if (sourceType == targetType) { Expression toListExp = Expression.Call(_toListMethod.MakeGenericMethod(sourceType), assignExpression); Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression)); finalAssign.Add(setIf); } } } } else // 来自其他映射器。 { var mapper = GetMapper(sourceType, targetType, false, item.Item4); if (mapper != null) { mapper.Initialize(_constructorFunc); Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(item.Item2.Type), item.Item2.Type); if (!IsListOf(propToAssign.Type)) { ChangParameterExpressionVisitor changeVisitor = new ChangParameterExpressionVisitor(propToAssign, assignExpression); Expression modifiedExpression = changeVisitor.Visit(mapper.expressionForExisting.Body); Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression); Expression setIf = Expression.IfThen(checkIfNull, modifiedExpression); assignExpression = setIf; } else { Expression selectExp = Expression.Call(_selectMethod.MakeGenericMethod(sourceType), Expression.Constant(mapper.GetDelegate())); Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression); Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression)); assignExpression = setIf; } finalAssign.Add(assignExpression); } } } if (finalAssign.Count > 0 && _delegateCallForExisting == null) { expressionForExisting = Expression.Lambda(Expression.Block(typeof(void), finalAssign), paramClassSource, paramTarget); // 编译 _delegateCallForExisting = expressionForExisting.Compile(); } } }
private static IProtoColumn <T> CreateProtoColumn(PropertyInfo propInfo) { Type type = typeof(T); Type propertyType = propInfo.PropertyType; LambdaExpression getter = null; LambdaExpression setter = null; Expression defaultExpr = Expression.Default(propertyType); Type getterType = typeof(Func <T, int>) .GetGenericTypeDefinition() .MakeGenericType(typeof(T), propertyType); Type setterType = typeof(Action <T, int>) .GetGenericTypeDefinition() .MakeGenericType(typeof(T), propertyType); if (propInfo.CanRead) { ParameterExpression objectParameter = Expression.Parameter(type); Expression propertyExpr = Expression.Property(objectParameter, propInfo); getter = Expression.Lambda(getterType, propertyExpr, objectParameter); } else { // return default value if the property has no getter method. ParameterExpression objectParameter = Expression.Parameter(type); getter = Expression.Lambda(getterType, defaultExpr, objectParameter); } if (propInfo.CanWrite) { ParameterExpression objectParameter = Expression.Parameter(type); ParameterExpression valueParameter = Expression.Parameter(propertyType); Expression propertyExpr = Expression.Property(objectParameter, propInfo); Expression assignExpr = Expression.Assign(propertyExpr, valueParameter); setter = Expression.Lambda(setterType, assignExpr, objectParameter, valueParameter); } else { ParameterExpression objectParameter = Expression.Parameter(type); ParameterExpression valueParameter = Expression.Parameter(propertyType); Expression emptyExpr = Expression.Empty(); setter = Expression.Lambda(setterType, emptyExpr, objectParameter, valueParameter); } ProtoColumnAttribute protoColumnAttribute = propInfo.GetCustomAttribute <ProtoColumnAttribute>(); IProtoValue valueMetadata = Proto <T> .CreateProtoValue(propertyType); Type genericDef = typeof(ProtoColumn <T, int>).GetGenericTypeDefinition(); Type target = genericDef.MakeGenericType(typeof(T), propertyType); ConstructorInfo constructorInfo = target.GetConstructors()[0]; return((IProtoColumn <T>)constructorInfo.Invoke( new object[] { propInfo, propInfo.Name, protoColumnAttribute.ID, valueMetadata, Expression.Lambda(defaultExpr).Compile().DynamicInvoke(), getter.Compile(), setter.Compile() } )); }
public MapperFuncs(MapRequest mapRequest, LambdaExpression typedExpression) { Typed = typedExpression.Compile(); _untyped = new Lazy <UntypedMapperFunc>(() => Wrap(mapRequest, typedExpression).Compile()); }
/// <summary> /// Возвращает относительный или абсолютный url (см. <paramref name="includeAuthority"/>) на основе контроллера с типом <typeparamref name="TModuleController"/> и метода, вызванного в лямбда-выражении <paramref name="expression"/>. /// </summary> /// <typeparam name="TModule">Тип модуля.</typeparam> /// <typeparam name="TModuleController">Тип контроллера, относящийся к модулю <typeparamref name="TModule"/>. Проверяются зарегистрированные типы контроллеров (<see cref="ModuleControllerTypesManager"/>) в модуле <typeparamref name="TModule"/> и проверяется нахождение типа <typeparamref name="TModuleController"/> в цепочках наследования.</typeparam> /// <param name="expression">Выражение, содержащее вызов метода контроллера, к которому следует построить маршрут. Все аргументы вызываемого метода должны быть указаны. Если аргумент указывается как null, то он игнорируется. Если аргумент задан явно, то он передается в адресе.</param> /// <param name="includeAuthority">Если равно true, то формируется абсолютный url, включающий в себя адрес сервера.</param> /// <returns>Возвращает сформированный url или генерирует исключение.</returns> /// <exception cref="ArgumentException">Исключение возникает, если в выражении <paramref name="expression"/> нет вызова метода или вызван метод, не относящийся к <typeparamref name="TModuleController"/>.</exception> /// <exception cref="NotSupportedException"> /// <para>Исключение возникает в ряде случаев: </para> /// <para>1) Тип контроллера не наследуется от <see cref="ModuleControllerUser{TModule}"/>/<see cref="ModuleControllerAdmin{TModule}"/>);</para> /// <para>2) Модуль с типом <typeparamref name="TModule"/> не найден в числе активных модулей;</para> /// <para>3) В списке контроллеров модуля <typeparamref name="TModule"/> не найден контроллер, тип которого наследуется или равен <typeparamref name="TModuleController"/>. Подразумевается, что вызов CreateRoute должен найти определенный action среди тех контроллеров модуля, которые будут откликаться на обработчик http-запроса. Если же передается контроллер, который не попадает в обработчик http-запроса, то нет смысла пытаться сформировать для него url;</para> /// <para>4) В списке контроллеров модуля <typeparamref name="TModule"/> найдено несколько контроллеров (скорее всего, пользовательский и администрирование), в цепочке наследования которых находится <typeparamref name="TModuleController"/>. Подразумевается, что невозможно определить, на основе каких правил формировать url - для администрирования подставляются префиксы /admin, для пользовательской части url формируется "как есть".</para> /// <para>5) Найден подходящий тип контроллера в модуле <typeparamref name="TModule"/>, однако на данный момент тип этого контроллера не поддерживается в <see cref="ControllerTypeFactory"/>, т.е. для этого контроллера нет подходящего обработчика http-запросов.</para> /// </exception> /// <exception cref="HandledException">Исключение возникает, если было сгенерировано любое другое нештатное исключение во время работы модуля.</exception> public Uri CreateRoute <TModule, TModuleController>(Expression <Func <TModuleController, ActionResult> > expression, bool includeAuthority = false) where TModule : ModuleCore <TModule> where TModuleController : IModuleController <TModule> { try { if (expression.Body.NodeType != ExpressionType.Call) { throw new HandledException("", new ArgumentException("Выражение должно содержать вызов метода.", nameof(expression))); } var module = AppCore.Get <TModule>(); if (module == null) { throw new HandledException("", new NotSupportedException($"Модуль типа '{typeof(TModule).FullName}' не найден среди активных модулей.")); } var controllerType = typeof(TModuleController); if (!controllerType.IsAssignableToGenericType(typeof(ModuleControllerUser <>)) && !controllerType.IsAssignableToGenericType(typeof(ModuleControllerUser <>))) { throw new HandledException("", new NotSupportedException($"Передаваемый тип контроллера должен быть наследником универсального типа {typeof(ModuleControllerUser<>).FullName} или {typeof(ModuleControllerAdmin<>).FullName}.")); } var controllerTypes = AppCore.Get <ModuleControllerTypesManager>().GetModuleControllerTypes <TModule>(); var controllerTypeCandidates = controllerTypes.Where(x => controllerType.IsAssignableFrom(x.Value)).ToList(); if (controllerTypeCandidates.Count == 0) { throw new HandledException("", new NotSupportedException($"Среди контроллеров модуля '{module.Caption}' нет контроллера, в цепочке наследования которого находится тип '{controllerType.FullName}'.")); } else if (controllerTypeCandidates.Count > 1) { throw new HandledException("", new NotSupportedException($"Среди контроллеров модуля '{module.Caption}' есть несколько контроллеров, в цепочке наследования котороых находится тип '{controllerType.FullName}'. Используйте в качестве {nameof(TModuleController)} другой тип, точно относящийся к одному из контроллеров, либо уменьшите общность наследования контроллеров модуля.")); } var controllerTypeCandidate = controllerTypeCandidates.First(); var controllerTypeFromFactory = ControllerTypeFactory.GetControllerTypes().Where(x => x.ControllerTypeID == controllerTypeCandidate.Key).FirstOrDefault(); if (controllerTypeFromFactory == null) { throw new HandledException("", new NotSupportedException($"Контроллер найден, но тип не поддерживается. См. '{typeof(ControllerTypeFactory).FullName}'.")); } var methodCall = (expression.Body as MethodCallExpression); if (!methodCall.Method.DeclaringType.IsAssignableFrom(controllerType)) { throw new HandledException("", new ArgumentException("Выражение должно вызывать метод указаного контроллера.", nameof(expression))); } var methodName = methodCall.Method.Name; var possibleActionAttribute = methodCall.Method.GetCustomAttributes <ModuleActionAttribute>(true).FirstOrDefault(); if (possibleActionAttribute != null && !string.IsNullOrEmpty(possibleActionAttribute.Alias)) { methodName = possibleActionAttribute.Alias; } var arguments = methodCall.Arguments.Select(x => { LambdaExpression lambda = Expression.Lambda(x); var compiledExpression = lambda.Compile(); var value = compiledExpression.DynamicInvoke(); return($"{value}"); }).ToList(); var defaultMethod = methodCall.Method.DeclaringType.GetMethod(nameof(ModuleControllerUser <OnWeb.Modules.WebCoreModule.WebCoreModule> .Index), BindingFlags.Public | BindingFlags.Instance, null, new Type[] { }, null); var isDefaultMethod = defaultMethod == methodCall.Method; if (isDefaultMethod && arguments.Count == 0) { methodName = null; } var url = controllerTypeFromFactory.CreateRelativeUrl(module.UrlName, methodName, arguments.ToArray()); return(includeAuthority ? new Uri(AppCore.ServerUrl, url) : new Uri(url, UriKind.Relative)); } catch (HandledException ex) { this.RegisterServiceEvent(EventType.Error, "Ошибка создания переадресации", null, ex.InnerException); throw ex.InnerException; } catch (Exception ex) { this.RegisterServiceEvent(EventType.Error, "Ошибка создания переадресации", null, ex); throw new HandledException("Ошибка переадресации", ex); } }
private static IOrderedEnumerable <TSource> Sort <TSource>(this IEnumerable <TSource> source, string keyPropertyName, IComparer comparer, bool descending, bool thenBy) { IOrderedEnumerable <TSource> result; string[] propertiesNames = keyPropertyName.Split('.'); Type type = typeof(TSource); ParameterExpression parameter = Expression.Parameter(type); Expression expression = parameter; foreach (string propertyName in propertiesNames) { PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); if (property != null && property.CanRead) { expression = Expression.Property(expression, property); type = property.PropertyType; } else { expression = null; type = null; break; } } if (expression != null && type != null) { Type delegateType = typeof(Func <,>).MakeGenericType(typeof(TSource), type); LambdaExpression lambda = Expression.Lambda(delegateType, expression, parameter); MethodInfo method; if (thenBy) { if (descending) { method = _ThenByDescendingMethodInfo.Value; } else { method = _ThenByMethodInfo.Value; } } else { if (descending) { method = _OrderByDescendingMethodInfo.Value; } else { method = _OrderByMethodInfo.Value; } } method = method.MakeGenericMethod(typeof(TSource), type); result = (IOrderedEnumerable <TSource>)method.Invoke(null, new object[] { source, lambda.Compile(), comparer }); } else { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type \"{0}\" does not contain a property \"{1}\"", typeof(TSource).FullName, keyPropertyName)); } return(result); }
private async Task <int> InternalUpdate <TEntity>(ObjectContext objectContext, EntityMap entityMap, ObjectQuery <TEntity> query, Expression <Func <TEntity, TEntity> > updateExpression, bool async = false) where TEntity : class { DbConnection updateConnection = null; DbTransaction updateTransaction = null; DbCommand updateCommand = null; bool ownConnection = false; bool ownTransaction = false; try { // get store connection and transaction var store = GetStore(objectContext); updateConnection = store.Item1; updateTransaction = store.Item2; if (updateConnection.State != ConnectionState.Open) { updateConnection.Open(); ownConnection = true; } // use existing transaction or create new if (updateTransaction == null) { updateTransaction = updateConnection.BeginTransaction(); ownTransaction = true; } updateCommand = updateConnection.CreateCommand(); updateCommand.Transaction = updateTransaction; if (objectContext.CommandTimeout.HasValue) { updateCommand.CommandTimeout = objectContext.CommandTimeout.Value; } var innerSelect = GetSelectSql(query, entityMap, updateCommand); var sqlBuilder = new StringBuilder(innerSelect.Length * 2); sqlBuilder.Append("UPDATE "); sqlBuilder.Append(removeSchema(entityMap.TableName)); sqlBuilder.AppendFormat(" AS j0 INNER JOIN (", removeSchema(entityMap.TableName)); sqlBuilder.AppendLine(); sqlBuilder.AppendLine(innerSelect); sqlBuilder.Append(") AS j1 ON ("); bool wroteKey = false; foreach (var keyMap in entityMap.KeyMaps) { if (wroteKey) { sqlBuilder.Append(" AND "); } sqlBuilder.AppendFormat("j0.{0} = j1.{0}", keyMap.ColumnName); wroteKey = true; } sqlBuilder.Append(")"); sqlBuilder.AppendLine(" "); sqlBuilder.AppendLine(" SET "); var memberInitExpression = updateExpression.Body as MemberInitExpression; if (memberInitExpression == null) { throw new ArgumentException("The update expression must be of type MemberInitExpression.", "updateExpression"); } int nameCount = 0; bool wroteSet = false; foreach (MemberBinding binding in memberInitExpression.Bindings) { if (wroteSet) { sqlBuilder.AppendLine(", "); } string propertyName = binding.Member.Name; string columnName = entityMap.PropertyMaps .Where(p => p.PropertyName == propertyName) .Select(p => p.ColumnName) .FirstOrDefault(); var memberAssignment = binding as MemberAssignment; if (memberAssignment == null) { throw new ArgumentException("The update expression MemberBinding must only by type MemberAssignment.", "updateExpression"); } Expression memberExpression = memberAssignment.Expression; ParameterExpression parameterExpression = null; memberExpression.Visit((ParameterExpression p) => { if (p.Type == entityMap.EntityType) { parameterExpression = p; } return(p); }); if (parameterExpression == null) { object value; if (memberExpression.NodeType == ExpressionType.Constant) { var constantExpression = memberExpression as ConstantExpression; if (constantExpression == null) { throw new ArgumentException( "The MemberAssignment expression is not a ConstantExpression.", "updateExpression"); } value = constantExpression.Value; } else { LambdaExpression lambda = Expression.Lambda(memberExpression, null); value = lambda.Compile().DynamicInvoke(); } if (value != null) { string parameterName = "p__update__" + nameCount++; var parameter = updateCommand.CreateParameter(); parameter.ParameterName = parameterName; parameter.Value = value; updateCommand.Parameters.Add(parameter); sqlBuilder.AppendFormat("{0} = @{1}", columnName, parameterName); } else { sqlBuilder.AppendFormat("{0} = NULL", columnName); } } else { // create clean objectset to build query from var objectSet = objectContext.CreateObjectSet <TEntity>(); Type[] typeArguments = new[] { entityMap.EntityType, memberExpression.Type }; ConstantExpression constantExpression = Expression.Constant(objectSet); LambdaExpression lambdaExpression = Expression.Lambda(memberExpression, parameterExpression); MethodCallExpression selectExpression = Expression.Call( typeof(Queryable), "Select", typeArguments, constantExpression, lambdaExpression); // create query from expression var selectQuery = objectSet.CreateQuery(selectExpression, entityMap.EntityType); string sql = selectQuery.ToTraceString(); // parse select part of sql to use as update string regex = @"SELECT\s*\r\n(?<ColumnValue>.+)?\s*AS\s*(?<ColumnAlias>\w+)\r\nFROM\s*(?<TableName>\w+\.\w+|\w+)\s*AS\s*(?<TableAlias>\w+)"; Match match = Regex.Match(sql, regex); if (!match.Success) { throw new ArgumentException("The MemberAssignment expression could not be processed.", "updateExpression"); } string value = match.Groups["ColumnValue"].Value; string alias = match.Groups["TableAlias"].Value; value = value.Replace(alias + ".", ""); foreach (ObjectParameter objectParameter in selectQuery.Parameters) { string parameterName = "p__update__" + nameCount++; var parameter = updateCommand.CreateParameter(); parameter.ParameterName = parameterName; parameter.Value = objectParameter.Value; updateCommand.Parameters.Add(parameter); value = value.Replace(objectParameter.Name, parameterName); } sqlBuilder.AppendFormat("{0} = {1}", columnName, value); } wroteSet = true; } updateCommand.CommandText = sqlBuilder.ToString().Replace("[", "").Replace("]", ""); int result = async ? await updateCommand.ExecuteNonQueryAsync().ConfigureAwait(false) : updateCommand.ExecuteNonQuery(); // only commit if created transaction if (ownTransaction) { updateTransaction.Commit(); } return(result); } finally { if (updateCommand != null) { updateCommand.Dispose(); } if (updateTransaction != null && ownTransaction) { updateTransaction.Dispose(); } if (updateConnection != null && ownConnection) { updateConnection.Close(); } } }
public static IQueryable OrderBy <T>(this IQueryable source, string ordering, Func <Type> getDynamicListTypeCallback, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (ordering == null) { throw new ArgumentNullException("ordering"); } IQueryable <T> typedSource = source as IQueryable <T>; if (!ordering.Contains(",")) { bool descending = false; if (ordering.IndexOf(" descending", StringComparison.CurrentCultureIgnoreCase) >= 0) { ordering = ordering.Replace(" descending", ""); descending = true; } if (ordering.IndexOf(" desc", StringComparison.CurrentCultureIgnoreCase) >= 0) { ordering = ordering.Replace(" desc", ""); descending = true; } LambdaExpression lambda = DynamicExpression.ParseLambda <T>(source.ElementType, typeof(object), ordering, false, values); if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(T)) { //source list is DynamicNode and the lambda returns a Func<object> Func <T, object> func = (Func <T, object>)lambda.Compile(); //get the values out var query = typedSource.ToList().ConvertAll(item => new { node = item, key = EvaluateDynamicNodeFunc(item, func) }); if (query.Count == 0) { return(source); } var types = from i in query group i by i.key.GetType() into g where g.Key != typeof(DynamicNull) orderby g.Count() descending select new { g, Instances = g.Count() }; var dominantType = types.First().g.Key; // NH - add culture dependencies StringComparer comp = StringComparer.Create(CultureInfo.CurrentCulture, true); if (!descending) { // if the dominant type is a string we'll ensure that strings are sorted based on culture settings on node if (dominantType.FullName == "System.String") { return(query.OrderBy(item => item.key.ToString(), comp).Select(item => item.node).AsQueryable()); } else { return(query.OrderBy(item => GetObjectAsTypeOrDefault(item.key, dominantType)).Select(item => item.node).AsQueryable()); } } else { if (dominantType.FullName == "System.String") { return(query.OrderByDescending(item => item.key.ToString(), comp).Select(item => item.node).AsQueryable()); } else { return(query.OrderByDescending(item => GetObjectAsTypeOrDefault(item.key, dominantType)).Select(item => item.node).AsQueryable()); } } } } bool isDynamicNodeList = false; if (typedSource != null) { isDynamicNodeList = true; } ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(source.ElementType, "") }; var parser = new ExpressionParser <T>(parameters, ordering, values, false); IEnumerable <DynamicOrdering> orderings = parser.ParseOrdering(); Expression queryExpr = source.Expression; string methodAsc = "OrderBy"; string methodDesc = "OrderByDescending"; foreach (DynamicOrdering o in orderings) { if (!isDynamicNodeList) { queryExpr = Expression.Call( typeof(Queryable), o.Ascending ? methodAsc : methodDesc, new Type[] { source.ElementType, o.Selector.Type }, queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters))); } else { //reroute each stacked Expression.Call into our own methods that know how to deal //with DynamicNode queryExpr = Expression.Call( getDynamicListTypeCallback(), o.Ascending ? methodAsc : methodDesc, null, queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)) ); } methodAsc = "ThenBy"; methodDesc = "ThenByDescending"; } if (isDynamicNodeList) { return(typedSource.Provider.CreateQuery(queryExpr)); } return(source.Provider.CreateQuery(queryExpr)); }
public static IQueryable Where <T>(this IQueryable source, string predicate, params object[] values) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } LambdaExpression lambda = DynamicExpression.ParseLambda <T>(source.ElementType, typeof(bool), predicate, true, values); if (lambda.Parameters.Count > 0 && lambda.Parameters[0].Type == typeof(T)) { //source list is DynamicNode and the lambda returns a Func<object> IQueryable <T> typedSource = source as IQueryable <T>; var compiledFunc = lambda.Compile(); Func <T, object> func = null; Func <T, bool> boolFunc = null; if (compiledFunc is Func <T, object> ) { func = (Func <T, object>)compiledFunc; } if (compiledFunc is Func <T, bool> ) { boolFunc = (Func <T, bool>)compiledFunc; } return(typedSource.Where(delegate(T node) { object value = -1; //value = func(node); //I can't figure out why this is double func<>'d try { if (func != null) { var firstFuncResult = func(node); if (firstFuncResult is Func <T, object> ) { value = (firstFuncResult as Func <T, object>)(node); } if (firstFuncResult is Func <T, bool> ) { value = (firstFuncResult as Func <T, bool>)(node); } if (firstFuncResult is bool) { return (bool)firstFuncResult; } if (value is bool) { return (bool)value; } } if (boolFunc != null) { return boolFunc(node); } return false; } catch (Exception ex) { Trace.WriteLine(ex.Message); return false; } }).AsQueryable()); } else { return(source.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, Expression.Quote(lambda)))); } }
public TResult Execute <TResult>(Expression expression) { _queryOptions = new QueryOptions(); _descending = false; Visit(expression); if (_select == null) { throw new NotSupportedException("Couchbase LINQ expressions require a Select statement"); } if (_reduce != null && _orderby != null) { throw new InvalidOperationException("Cannot both reduce and sort the same query"); } var query = default(Query); if (_where != null) { var view = SetupView(); query = view.CreateQuery(); } else { query = _db.CreateAllDocumentsQuery(); } query.Skip = _queryOptions.Skip; query.Limit = _queryOptions.Limit; query.Descending = _queryOptions.Descending; var results = default(QueryEnumerator); if (_orderby == null) { results = query.Run(); return(_reduce != null ? (TResult)results.First().Value : (TResult)GetTypedKeys <TResult>(results)); } // OrderBy needs to defer skip and limit to the end var skip = query.Skip; var limit = query.Limit; query.Skip = 0; query.Limit = Int32.MaxValue; results = query.Run(); var realized = ((IEnumerable <QueryRow>)results).ToList(); var compiled = _orderby.Compile(); realized.Sort((x, y) => { var xVal = compiled.DynamicInvoke(x); var yVal = compiled.DynamicInvoke(y); var xComp = xVal as IComparable; if (xComp != null) { var yComp = yVal as IComparable; return(_descending ? yComp.CompareTo(xComp) : xComp.CompareTo(yComp)); } return(_descending ? Comparer <object> .Default.Compare(yVal, xVal) : Comparer <object> .Default.Compare(xVal, yVal)); }); return((TResult)GetTypedKeys <TResult>(realized, skip, limit)); }
public static object ExecuteLambda(LambdaExpression lambdaExpression, params object[] args) { ArgumentUtility.CheckNotNull("args", args); return(lambdaExpression.Compile().DynamicInvoke(args)); }
protected override void VisitLambda(LambdaExpression lambda) { Push(lambda.Compile(this)); }
public void CannotRethrowOutsideCatch(bool useInterpreter) { LambdaExpression rethrowNothing = Expression.Lambda <Action>(Expression.Rethrow()); Assert.Throws <InvalidOperationException>(() => rethrowNothing.Compile(useInterpreter)); }
public CompiledExpression(LambdaExpression expression) { _expression = expression; _func = _expression.Compile(); }
private void BuildProjector(LambdaExpression projectionLambda, LambdaExpression aggregator, out Delegate projector, out Delegate asyncProjector) { var sqlQueryProviderParam = Expression.Parameter(typeof(SqlQueryProvider)); var formatResultsParam = Expression.Parameter(typeof(SqlQueryFormatResult)); var placeholderValuesParam = Expression.Parameter(typeof(object[])); var elementType = projectionLambda.ReturnType; Expression executor; if (elementType.IsDataAccessObjectType()) { var concreteElementType = this.DataAccessModel.GetConcreteTypeFromDefinitionType(elementType); var constructor = typeof(DataAccessObjectProjector <,>).MakeGenericType(elementType, concreteElementType).GetConstructors(BindingFlags.Public | BindingFlags.Instance).Single(); executor = Expression.New ( constructor, sqlQueryProviderParam, Expression.Constant(this.DataAccessModel), Expression.Constant(this.SqlDatabaseContext), formatResultsParam, placeholderValuesParam, projectionLambda ); } else { if ((aggregator?.Body as MethodCallExpression)?.Method.GetGenericMethodOrRegular() == MethodInfoFastRef.EnumerableExtensionsAlwaysReadFirstMethod) { var constructor = typeof(AlwaysReadFirstObjectProjector <,>).MakeGenericType(projectionLambda.ReturnType, projectionLambda.ReturnType).GetConstructors(BindingFlags.Public | BindingFlags.Instance).Single(); executor = Expression.New ( constructor, sqlQueryProviderParam, Expression.Constant(this.DataAccessModel), Expression.Constant(this.SqlDatabaseContext), formatResultsParam, placeholderValuesParam, projectionLambda ); } else { var constructor = typeof(ObjectProjector <,>).MakeGenericType(projectionLambda.ReturnType, projectionLambda.ReturnType).GetConstructors(BindingFlags.Public | BindingFlags.Instance).Single(); executor = Expression.New ( constructor, sqlQueryProviderParam, Expression.Constant(this.DataAccessModel), Expression.Constant(this.SqlDatabaseContext), formatResultsParam, placeholderValuesParam, projectionLambda ); } } var asyncExecutor = executor; var cancellationToken = Expression.Parameter(typeof(CancellationToken)); if (aggregator != null) { var originalExecutor = executor; var aggr = aggregator; var newBody = SqlConstantPlaceholderReplacer.Replace(aggr.Body, placeholderValuesParam); executor = SqlExpressionReplacer.Replace(newBody, aggr.Parameters[0], originalExecutor); newBody = ProjectionAsyncRewriter.Rewrite(newBody, cancellationToken); asyncExecutor = SqlExpressionReplacer.Replace(newBody, aggr.Parameters[0], originalExecutor); } projectionLambda = Expression.Lambda(executor, sqlQueryProviderParam, formatResultsParam, placeholderValuesParam); var asyncProjectorLambda = Expression.Lambda(asyncExecutor, sqlQueryProviderParam, formatResultsParam, placeholderValuesParam, cancellationToken); ProjectorCacheInfo cacheInfo; var key = new ProjectorCacheKey(projectionLambda); var oldCache = this.SqlDatabaseContext.projectorCache; if (!oldCache.TryGetValue(key, out cacheInfo)) { cacheInfo.projector = projectionLambda.Compile(); cacheInfo.asyncProjector = asyncProjectorLambda.Compile(); if (this.SqlDatabaseContext.projectorCache.Count >= ProjectorCacheMaxLimit) { ProjectionExpressionCacheLogger.Info(() => $"Projector has been flushed because it overflowed with a size of {ProjectionExpressionCacheMaxLimit}\n\nProjector: {projectionLambda}\n\nAt: {new StackTrace()}"); var newCache = new Dictionary <ProjectorCacheKey, ProjectorCacheInfo>(ProjectorCacheMaxLimit, ProjectorCacheEqualityComparer.Default); foreach (var value in oldCache.Take(oldCache.Count / 3)) { newCache[value.Key] = value.Value; } newCache[key] = cacheInfo; this.SqlDatabaseContext.projectorCache = newCache; } else { var newCache = new Dictionary <ProjectorCacheKey, ProjectorCacheInfo>(oldCache, ProjectorCacheEqualityComparer.Default) { [key] = cacheInfo }; this.SqlDatabaseContext.projectorCache = newCache; } ProjectionCacheLogger.Info(() => $"Cached projector:\n{cacheInfo.projector}"); ProjectionCacheLogger.Debug(() => $"Projector Cache Size: {this.SqlDatabaseContext.projectionExpressionCache.Count}"); } projector = cacheInfo.projector; asyncProjector = cacheInfo.asyncProjector; }
/// <summary> /// 将集合转换为数据集。 /// </summary> /// <param name="list">集合。</param> /// <param name="t">转换的元素类型。</param> /// <param name="generic">是否生成泛型数据集。</param> /// <returns>转换后的数据集。</returns> private static DataSet ListToDataSet(IEnumerable list, Type t, bool generic) { DataSet ds = new DataSet("Data"); if (t == null) { if (list != null) { foreach (var i in list) { if (i == null) { continue; } t = i.GetType(); break; } } if (t == null) { return(ds); } } ds.Tables.Add(t.Name); //如果集合中元素为DataSet扩展涉及到的基本类型时,进行特殊转换。 if (t.IsValueType || t == typeof(string)) { ds.Tables[0].TableName = "Info"; ds.Tables[0].Columns.Add(t.Name); if (list != null) { foreach (var i in list) { DataRow addRow = ds.Tables[0].NewRow(); addRow[t.Name] = i; ds.Tables[0].Rows.Add(addRow); } } return(ds); } //处理模型的字段和属性。 var fields = t.GetFields(); var properties = t.GetProperties(); foreach (var j in fields) { if (!ds.Tables[0].Columns.Contains(j.Name)) { if (generic) { ds.Tables[0].Columns.Add(j.Name, j.FieldType); } else { ds.Tables[0].Columns.Add(j.Name); } } } foreach (var j in properties) { if (!ds.Tables[0].Columns.Contains(j.Name)) { if (generic) { ds.Tables[0].Columns.Add(j.Name, j.PropertyType); } else { ds.Tables[0].Columns.Add(j.Name); } } } if (list == null) { return(ds); } //读取list中元素的值。 foreach (var i in list) { if (i == null) { continue; } DataRow addRow = ds.Tables[0].NewRow(); foreach (var j in fields) { MemberExpression field = Expression.Field(Expression.Constant(i), j.Name); LambdaExpression lambda = Expression.Lambda(field, new ParameterExpression[] { }); Delegate func = lambda.Compile(); object value = func.DynamicInvoke(); addRow[j.Name] = value; } foreach (var j in properties) { MemberExpression property = Expression.Property(Expression.Constant(i), j); LambdaExpression lambda = Expression.Lambda(property, new ParameterExpression[] { }); Delegate func = lambda.Compile(); object value = func.DynamicInvoke(); addRow[j.Name] = value; } ds.Tables[0].Rows.Add(addRow); } return(ds); }
private static string ExpressionResult(LambdaExpression expr, Context context) { return(JsonConvert.SerializeObject(expr.Compile().DynamicInvoke(context))); }
/// <summary> /// TBD /// </summary> /// <param name="expression">TBD</param> /// <returns>TBD</returns> public Delegate Compile(LambdaExpression expression) { return(expression.Compile()); }
public static object At(this LambdaExpression f, params object[] args) { return(f.Compile().DynamicInvoke(args)); }
private void ParseQueryCondition( BinaryExpression binaryExpression, StringBuilder queryBuilder) { bool swap; string column = this.GetConditionColumn(binaryExpression, out swap); queryBuilder.Append(column); ExpressionType expressionType = binaryExpression.NodeType; if (swap) { expressionType = OppositeExpression(expressionType); } LambdaExpression valueExpression = Expression.Lambda( swap ? binaryExpression.Left : binaryExpression.Right); object value = valueExpression.Compile().DynamicInvoke(); bool valueIsInt = false; if (value != null) { if (IsIntegerType(value.GetType())) { valueIsInt = true; } else { value = value.ToString(); } } switch (expressionType) { case ExpressionType.Equal: if (value == null) { queryBuilder.Append(" IS NULL"); } else if (valueIsInt) { queryBuilder.Append(" = "); queryBuilder.Append(value); } else { queryBuilder.Append(" = ?"); this.whereParameters.Add(value); } return; case ExpressionType.NotEqual: if (value == null) { queryBuilder.Append(" IS NOT NULL"); } else if (valueIsInt) { queryBuilder.Append(" <> "); queryBuilder.Append(value); } else { queryBuilder.Append(" <> ?"); this.whereParameters.Add(value); } return; } if (value == null) { throw new InvalidOperationException( "A null value was used in a greater-than/less-than operation."); } if (!valueIsInt) { throw new NotSupportedException( "Greater-than/less-than operators not supported on strings."); } switch (expressionType) { case ExpressionType.LessThan: queryBuilder.Append(" < "); break; case ExpressionType.LessThanOrEqual: queryBuilder.Append(" <= "); break; case ExpressionType.GreaterThan: queryBuilder.Append(" > "); break; case ExpressionType.GreaterThanOrEqual: queryBuilder.Append(" >= "); break; default: throw new NotSupportedException( "Unsupported query expression type: " + expressionType); } queryBuilder.Append(value); }
public OriginalStatement(LambdaExpression expression) { Delegate = expression.Compile(); Expression = expression; }
internal void PerformJoin( TableInfo tableInfo, Type recordType, IQueryable joinTable, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector) { if (joinTable == null) { throw new ArgumentNullException("joinTable"); } if (tableInfo != null) { this.tables.Add(tableInfo); this.recordTypes.Add(recordType); this.selectors.Add(outerKeySelector.Parameters[0].Name); } PropertyInfo tableInfoProp = joinTable.GetType().GetProperty("TableInfo"); if (tableInfoProp == null) { throw new NotSupportedException( "Cannot join with object: " + joinTable.GetType().Name + "; join is only supported on another QTable."); } TableInfo joinTableInfo = (TableInfo)tableInfoProp.GetValue(joinTable, null); if (joinTableInfo == null) { throw new InvalidOperationException("Missing join table info."); } this.tables.Add(joinTableInfo); this.recordTypes.Add(joinTable.ElementType); this.selectors.Add(innerKeySelector.Parameters[0].Name); this.projectionDelegates.Add(resultSelector.Compile()); int joinColumnCount = this.joinColumns.Count; this.FindColumns(outerKeySelector.Body, this.joinColumns); if (this.joinColumns.Count > joinColumnCount + 1) { throw new NotSupportedException("Join operations involving " + "multiple columns are not supported."); } else if (this.joinColumns.Count != joinColumnCount + 1) { throw new InvalidOperationException("Bad outer key selector for join."); } this.FindColumns(innerKeySelector.Body, this.joinColumns); if (this.joinColumns.Count > joinColumnCount + 2) { throw new NotSupportedException("Join operations involving " + "multiple columns not are supported."); } if (this.joinColumns.Count != joinColumnCount + 2) { throw new InvalidOperationException("Bad inner key selector for join."); } }
public static object GetValue(LambdaExpression expression) { var del = expression.Compile(); return(del.DynamicInvoke()); }
public static dynamic GetValue <T>(this T t, string propName) where T : class { LambdaExpression getter = BuildGetter <T>(propName); return(getter.Compile().DynamicInvoke(t));; }
/// <summary> /// Gets the expression argument value. /// </summary> /// <param name="element">The expression element.</param> /// <returns>The value.</returns> private static object GetArgumentValue(Expression element) { LambdaExpression l = Expression.Lambda(Expression.Convert(element, element.Type)); return(l.Compile().DynamicInvoke()); }
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Reflection; using System.Text.RegularExpressions; namespace Ssz.Utils { /// <summary> /// /// </summary> public static class ObjectHelper { #region public functions /// <summary> /// Returns all fields except that with Searchable(false) attribute. /// </summary> /// <param name="obj"></param> /// <returns></returns> public static IEnumerable<FieldInfo> GetAllFields(object obj) { Type? type = obj.GetType(); var fields = new List<FieldInfo>(); while (type is not null) { foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { SearchableAttribute? searchableAttribute = Attribute.GetCustomAttribute(fieldInfo, typeof(SearchableAttribute)) as SearchableAttribute; if (searchableAttribute is not null) { if (searchableAttribute.Searchable) fields.Add(fieldInfo); continue; } fields.Add(fieldInfo); } type = type.BaseType; } return fields; } /// <summary> /// Returns value of 'obj' concatenated with expression. /// If ivalid expression returns null. /// expression examples: ".Name", ".SubObjects[0].Name" /// </summary> /// <param name="obj"></param> /// <param name="expression"></param> /// <returns></returns> public static object? GetValue(object obj, string? expression) { if (String.IsNullOrEmpty(expression)) return null; try { ParameterExpression pObj = Expression.Parameter(obj.GetType(), @"obj"); LambdaExpression e = DynamicExpressionParser.ParseLambda(new[] { pObj }, null, @"obj" + expression); Delegate d = e.Compile(); return d.DynamicInvoke(obj); } catch (Exception) { return null; } } /// <summary> /// Sets value of 'obj' concatenated with expression. /// Returns True if succeeded. /// expression examples: ".Name", ".SubObjects[0].Name" /// </summary> /// <param name="obj"></param> /// <param name="expression"></param> /// <param name="value"></param> /// <returns></returns> public static bool SetValue(object obj, string? expression, object? value) { if (String.IsNullOrEmpty(expression)) return false; object o = obj; string[] parts = expression!.Split(new[] { '.' }, StringSplitOptions.None); if (parts.Length < 2 || !String.IsNullOrEmpty(parts[0])) return false; for (int i = 1; i < parts.Length - 1; i++) { Type t = o.GetType(); PropertyInfo? pi = t.GetProperty(parts[i]); if (pi is null || !pi.CanRead) return false; object? v = pi.GetValue(o); if (v is null) { if (!pi.CanWrite) return false; try { v = Activator.CreateInstance(pi.PropertyType); } catch { return false; } if (v is null) return false; pi.SetValue(o, v); } o = v; } return SetPropertyValue(o, parts[parts.Length - 1], value); } /// <summary> /// Returns True if succeeded. /// </summary> /// <param name="obj"></param> /// <param name="propertyName"></param> /// <param name="value"></param> /// <returns></returns> public static bool SetPropertyValue(object obj, string? propertyName, object? value) { if (String.IsNullOrEmpty(propertyName)) return false; try { Type t = obj.GetType(); PropertyInfo? pi = t.GetProperty(propertyName); if (pi is null || !pi.CanWrite) return false; if (value is null) { pi.SetValue(obj, null); } else { pi.SetValue(obj, new Any(value).ValueAs(pi.PropertyType, false)); } return true; } catch (Exception) { return false; } } /// <summary> /// Searches in properties with [Searchable(true)] or [Browsable(true)] attributes. /// [Searchable(true)] attribute has higher priority. /// If regex is null matches all properties. /// </summary> public static List<StringPropertyInfo> FindInStringBrowsableProperties(object obj, Regex? regex) { var result = new List<StringPropertyInfo>(); foreach (PropertyDescriptor propertyDescriptor in GetProperties(obj)) { object? value = propertyDescriptor.GetValue(obj); if (value is null) continue; var stringValue = value as string; if (stringValue is not null) { bool match = regex is not null ? regex.Match(stringValue).Success : true; if (match) { result.Add(new StringPropertyInfo { PropertyPath = propertyDescriptor.Name, PropertyValue = stringValue, }); } continue; } var listValue = value as IList; if (listValue is not null) { for (int i = 0; i < listValue.Count; i++) { object? item = listValue[i]; if (item is null) continue; foreach ( StringPropertyInfo subPropertyInfo in FindInStringBrowsableProperties(item, regex)) { subPropertyInfo.PropertyPath = propertyDescriptor.Name + @"[" + i + @"]." + subPropertyInfo.PropertyPath; result.Add(subPropertyInfo); } } continue; } foreach (StringPropertyInfo subPropertyInfo in FindInStringBrowsableProperties(value, regex)) { subPropertyInfo.PropertyPath = propertyDescriptor.Name + @"." + subPropertyInfo.PropertyPath; result.Add(subPropertyInfo); } } return result; } /// <summary> /// Replaces in properties with [Searchable(true)] or [Browsable(true)] attributes. /// [Searchable(true)] attribute has higher priority. /// </summary> public static List<StringPropertyInfo> ReplaceInStringBrowsableProperties(object obj, Regex regex, string replacement) { if (replacement is null) replacement = @""; var result = new List<StringPropertyInfo>(); foreach (PropertyDescriptor propertyDescriptor in GetProperties(obj)) { object? value = propertyDescriptor.GetValue(obj); if (value is null) continue; var stringValue = value as string; if (stringValue is not null) { if (!propertyDescriptor.IsReadOnly) { string newStringValue = regex.Replace(stringValue, replacement); if (newStringValue != stringValue) { propertyDescriptor.SetValue(obj, newStringValue); result.Add(new StringPropertyInfo { PropertyPath = propertyDescriptor.Name, PropertyValue = newStringValue, }); } } continue; } var listValue = value as IList; if (listValue is not null) { for (int i = 0; i < listValue.Count; i++) { object? item = listValue[i]; if (item is not null) { foreach ( StringPropertyInfo subPropertyInfo in ReplaceInStringBrowsableProperties(item, regex, replacement)) { subPropertyInfo.PropertyPath = propertyDescriptor.Name + @"[" + i + @"]." + subPropertyInfo.PropertyPath; result.Add(subPropertyInfo); } } } continue; } foreach (StringPropertyInfo subPropertyInfo in ReplaceInStringBrowsableProperties(value, regex, replacement)) { subPropertyInfo.PropertyPath = propertyDescriptor.Name + @"." + subPropertyInfo.PropertyPath; result.Add(subPropertyInfo); } } return result; } #endregion #region private functions /// <summary> /// Returns all Browsable properties of object. /// SearchableAttribute can explicitly set whether to return or not the property. /// </summary> private static IEnumerable<PropertyDescriptor> GetProperties(object obj) { var result = new List<PropertyDescriptor>(); foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(obj) .OfType<PropertyDescriptor>()) { SearchableAttribute? searchableAttribute = propertyDescriptor.Attributes.OfType<SearchableAttribute>().FirstOrDefault(); if (searchableAttribute is not null) { if (searchableAttribute.Searchable) result.Add(propertyDescriptor); continue; } if (propertyDescriptor.IsBrowsable) { result.Add(propertyDescriptor); } } return result; } #endregion } /// <summary> /// /// </summary> public class StringPropertyInfo { #region public functions /// <summary> /// Without '.' at the beginning. /// </summary> public string PropertyPath = ""; /// <summary> /// /// </summary> public string PropertyValue = ""; #endregion } /// <summary> /// For find and replace in string properties support. /// </summary> public sealed class SearchableAttribute : Attribute { #region construction and destruction /// <summary> /// /// </summary> /// <param name="searchable"></param> public SearchableAttribute(bool searchable) { Searchable = searchable; } #endregion #region public functions /// <summary> /// /// </summary> public bool Searchable { get; private set; } #endregion } }
public MapperFuncs(MapRequest mapRequest, LambdaExpression typedExpression) { Typed = typedExpression.Compile(); Untyped = Wrap(mapRequest, Typed).Compile(); }
private static object EvaluateLambda(LambdaExpression expression, object[] arguments) { return(expression.Compile().DynamicInvoke(arguments)); }
public static TDelegate?Compile <TDelegate>(this LambdaExpression?lambdaExpression) where TDelegate : Delegate { return(lambdaExpression?.Compile() as TDelegate); }
public override Serialization.Action <T, object> CreateSet <T>(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo)); // use reflection for structs // expression doesn't correctly set value if (propertyInfo.DeclaringType.IsValueType()) { return(LateBoundReflectionDelegateFactory.Instance.CreateSet <T>(propertyInfo)); } Type instanceType = typeof(T); Type valueType = typeof(object); ParameterExpression instanceParameter = Expression.Parameter(instanceType, "instance"); ParameterExpression valueParameter = Expression.Parameter(valueType, "value"); Expression readValueParameter = EnsureCastExpression(valueParameter, propertyInfo.PropertyType); MethodInfo setMethod = propertyInfo.GetSetMethod(true); Expression setExpression; if (setMethod.IsStatic) { setExpression = Expression.Call(setMethod, readValueParameter); } else { Expression readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType); setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter); } LambdaExpression lambdaExpression = Expression.Lambda(typeof(Serialization.Action <T, object>), setExpression, instanceParameter, valueParameter); Serialization.Action <T, object> compiled = (Serialization.Action <T, object>)lambdaExpression.Compile(); return(compiled); }