コード例 #1
0
        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);
        }
コード例 #2
0
        /// <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();
                }
            }
        }
コード例 #3
0
ファイル: Proto.cs プロジェクト: xgray/dotnet
        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()
            }
                       ));
        }
コード例 #4
0
 public MapperFuncs(MapRequest mapRequest, LambdaExpression typedExpression)
 {
     Typed    = typedExpression.Compile();
     _untyped = new Lazy <UntypedMapperFunc>(() => Wrap(mapRequest, typedExpression).Compile());
 }
コード例 #5
0
ファイル: RoutingManager.cs プロジェクト: Sellec/OnWeb
        /// <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);
            }
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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();
                }
            }
        }
コード例 #8
0
        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));
        }
コード例 #9
0
        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))));
            }
        }
コード例 #10
0
        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));
        }
コード例 #11
0
ファイル: ExpressionHelper.cs プロジェクト: maumar/Relinq
        public static object ExecuteLambda(LambdaExpression lambdaExpression, params object[] args)
        {
            ArgumentUtility.CheckNotNull("args", args);

            return(lambdaExpression.Compile().DynamicInvoke(args));
        }
コード例 #12
0
 protected override void VisitLambda(LambdaExpression lambda)
 {
     Push(lambda.Compile(this));
 }
コード例 #13
0
        public void CannotRethrowOutsideCatch(bool useInterpreter)
        {
            LambdaExpression rethrowNothing = Expression.Lambda <Action>(Expression.Rethrow());

            Assert.Throws <InvalidOperationException>(() => rethrowNothing.Compile(useInterpreter));
        }
コード例 #14
0
 public CompiledExpression(LambdaExpression expression)
 {
     _expression = expression;
     _func       = _expression.Compile();
 }
コード例 #15
0
        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;
        }
コード例 #16
0
        /// <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)));
 }
コード例 #18
0
 /// <summary>
 /// TBD
 /// </summary>
 /// <param name="expression">TBD</param>
 /// <returns>TBD</returns>
 public Delegate Compile(LambdaExpression expression)
 {
     return(expression.Compile());
 }
コード例 #19
0
ファイル: Maxima.cs プロジェクト: ststeiger/MaximaSharp
 public static object At(this LambdaExpression f, params object[] args)
 {
     return(f.Compile().DynamicInvoke(args));
 }
コード例 #20
0
ファイル: Query.cs プロジェクト: yfguo8/oneget
        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);
        }
コード例 #21
0
 public OriginalStatement(LambdaExpression expression)
 {
     Delegate   = expression.Compile();
     Expression = expression;
 }
コード例 #22
0
ファイル: Query.cs プロジェクト: yfguo8/oneget
        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.");
            }
        }
コード例 #23
0
        public static object GetValue(LambdaExpression expression)
        {
            var del = expression.Compile();

            return(del.DynamicInvoke());
        }
コード例 #24
0
        public static dynamic GetValue <T>(this T t, string propName) where T : class
        {
            LambdaExpression getter = BuildGetter <T>(propName);

            return(getter.Compile().DynamicInvoke(t));;
        }
コード例 #25
0
        /// <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());
        }
コード例 #26
0
ファイル: ObjectHelper.cs プロジェクト: ru-petrovi4/Ssz.Utils
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
    }
}
コード例 #27
0
 public MapperFuncs(MapRequest mapRequest, LambdaExpression typedExpression)
 {
     Typed   = typedExpression.Compile();
     Untyped = Wrap(mapRequest, Typed).Compile();
 }
コード例 #28
0
 private static object EvaluateLambda(LambdaExpression expression, object[] arguments)
 {
     return(expression.Compile().DynamicInvoke(arguments));
 }
コード例 #29
0
 public static TDelegate?Compile <TDelegate>(this LambdaExpression?lambdaExpression)
     where TDelegate : Delegate
 {
     return(lambdaExpression?.Compile() as TDelegate);
 }
コード例 #30
0
        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);
        }