private bool ShouldSkipProperty(AccessorMember member, OperationContext operationContext) { var name = member.Name; if (name == nameof(ITableEntity.PartitionKey) || name == nameof(ITableEntity.RowKey) || name == nameof(ITableEntity.Timestamp) || name == nameof(ITableEntity.ETag)) { return(true); } if (!member.CanRead || !member.CanWrite) { _logger?.LogInformation( "Omitting property '{0}' from serialization/de-serialization because the property's getter/setter are not public.", member.Name); return(true); } if (member.HasAttribute <IgnorePropertyAttribute>()) { _logger?.LogInformation( FormatLine(operationContext, $"Omitting property '{0}' from serialization/de-serialization because {nameof(IgnorePropertyAttribute)} has been set on that property.", member.Name)); return(true); } return(false); }
private static bool IsValueType(AccessorMember x) { if (IsValueCollection(x)) { return(true); // value collection } return(!x.Type.ImplementsGeneric(typeof(IEnumerable <>))); }
private static string GetClusterName(AccessorMember member) { var name = member.TryGetAttribute(out DisplayNameAttribute display) ? display.DisplayName ?? member.Name : member.Name; return(name); }
// ASP.NET Core MVC conventionally removes "Async" from the end of class methods private string ResolveActionName(AccessorMember method) { const string suffix = "Async"; return(_options.Value.SuppressAsyncSuffixInActionNames && method.Name.EndsWith(suffix, StringComparison.Ordinal) ? method.Name.Substring(0, method.Name.Length - suffix.Length) : method.Name); }
public bool IsSaved(AccessorMember member) { if (!member.TryGetAttribute(out DatabaseGeneratedAttribute attribute)) { return(true); } return(attribute.DatabaseGeneratedOption switch { DatabaseGeneratedOption.None => true, DatabaseGeneratedOption.Identity => false, DatabaseGeneratedOption.Computed => false, _ => throw new ArgumentOutOfRangeException() });
public static IBuildContext BuildAssociationSelectMany(ExpressionBuilder builder, BuildInfo buildInfo, TableBuilder.TableContext tableContext, AccessorMember onMember, AssociationDescriptor descriptor, ref bool isOuter) { var elementType = descriptor.GetElementType(builder.MappingSchema); var queryMethod = CreateAssociationQueryLambda( builder, onMember, descriptor, tableContext.OriginalType, tableContext.ObjectType, elementType, false, isOuter, tableContext.LoadWith, out isOuter); var parentRef = new ContextRefExpression(queryMethod.Parameters[0].Type, tableContext); var body = queryMethod.GetBody(parentRef); IBuildContext context; context = builder.BuildSequence(new BuildInfo(buildInfo, body)); context.SelectQuery.From.Tables[0].Alias = descriptor.GenerateAlias(); return(context); }
private static string GetHttpTemplate(DynamicHttpMethodAttribute httpMethod, AccessorMember member) { if (member.DeclaringType != null) { if (member.DeclaringType.TryGetAttribute <RouteAttribute>(true, out var routeAttribute)) { var baseTemplate = routeAttribute.Template; return(!string.IsNullOrWhiteSpace(httpMethod.Template) ? $"{baseTemplate}/{httpMethod.Template}" : baseTemplate); } } if (httpMethod.Template == string.Empty) { return(string.Empty); } return(!string.IsNullOrWhiteSpace(httpMethod.Template) ? httpMethod.Template : default);
public PropertyAccessor(ITypeReadAccessor reads, ITypeWriteAccessor writes, Type type, string name) { Type = type; Name = name; _reads = reads; _writes = writes; var members = AccessorMembers.Create(type); Info = members.PropertyInfo.SingleOrDefault(m => m.Name == name); var member = members.SingleOrDefault(p => p.Name == name); if (member == null) { return; } _member = member; }
public static IBuildContext BuildAssociationInline(ExpressionBuilder builder, BuildInfo buildInfo, TableBuilder.TableContext tableContext, AccessorMember onMember, AssociationDescriptor descriptor, bool inline, ref bool isOuter) { var elementType = descriptor.GetElementType(builder.MappingSchema); var parentExactType = descriptor.GetParentElementType(); var queryMethod = CreateAssociationQueryLambda( builder, onMember, descriptor, tableContext.OriginalType, parentExactType, elementType, inline, isOuter, tableContext.LoadWith, out isOuter); var parentRef = new ContextRefExpression(queryMethod.Parameters[0].Type, tableContext); var body = queryMethod.GetBody(parentRef); var context = builder.BuildSequence(new BuildInfo(tableContext, body, new SelectQuery())); var tableSource = tableContext.SelectQuery.From.Tables.First(); var join = new SqlFromClause.Join(isOuter ? JoinType.OuterApply : JoinType.CrossApply, context.SelectQuery, descriptor.GenerateAlias(), true, null); tableSource.Joins.Add(join.JoinedTable); return(new AssociationContext(builder, descriptor, tableContext, context, join.JoinedTable)); }
// Returns // (ParentType p) => dc.GetTable<ObjectType>().Where(...) // (ParentType p) => dc.GetTable<ObjectType>().Where(...).DefaultIfEmpty public static LambdaExpression CreateAssociationQueryLambda(ExpressionBuilder builder, AccessorMember onMember, AssociationDescriptor association, Type parentOriginalType, Type parentType, Type objectType, bool inline, bool enforceDefault, List <LoadWithInfo[]>?loadWith, out bool isLeft) { var dataContextConstant = Expression.Constant(builder.DataContext, builder.DataContext.GetType()); // We are trying to keep fast cache hit behaviour, so cache check should be added only if needed // bool shouldAddCacheCheck = false; bool cacheCheckAdded = false; LambdaExpression?definedQueryMethod = null; if (association.HasQueryMethod()) { // here we tell for Expression Comparer to compare optimized Association expressions // definedQueryMethod = (LambdaExpression)builder.AddQueryableMemberAccessors(onMember, builder.DataContext, (mi, dc) => { var queryLambda = association.GetQueryMethod(parentType, objectType) ?? throw new InvalidOperationException(); var optimizationContext = new ExpressionTreeOptimizationContext(dc); var optimizedExpr = optimizationContext.ExposeExpression(queryLambda); optimizedExpr = optimizationContext.ExpandQueryableMethods(optimizedExpr); return(optimizedExpr); }); cacheCheckAdded = true; var parameterMatch = new Dictionary <ParameterExpression, Expression>(); if (onMember.Arguments == null) { if (definedQueryMethod.Parameters.Count > 1 && typeof(IDataContext).IsSameOrParentOf(definedQueryMethod.Parameters[1].Type)) { parameterMatch.Add(definedQueryMethod.Parameters[1], dataContextConstant); } } else { var definedCount = definedQueryMethod.Parameters.Count; var argumentsCount = onMember.Arguments.Count; var diff = definedCount - argumentsCount; for (int i = definedCount - 1; i >= diff; i--) { parameterMatch.Add(definedQueryMethod.Parameters[i], onMember.Arguments[i - diff]); } } var body = definedQueryMethod.Body.Transform(parameterMatch, static (parameterMatch, e) =>
// Returns // (ParentType p) => dc.GetTable<ObjectType>().Where(...) // (ParentType p) => dc.GetTable<ObjectType>().Where(...).DefaultIfEmpty public static LambdaExpression CreateAssociationQueryLambda(ExpressionBuilder builder, AccessorMember onMember, AssociationDescriptor association, Type parentOriginalType, Type parentType, Type objectType, bool inline, bool enforceDefault, List <LoadWithInfo[]>?loadWith, out bool isLeft) { var dataContextConstant = Expression.Constant(builder.DataContext, builder.DataContext.GetType()); // We are trying to keep fast cache hit behaviour, so cache check should be added only if needed // bool shouldAddCacheCheck = false; bool cacheCheckAdded = false; LambdaExpression?definedQueryMethod = null; if (association.HasQueryMethod()) { // here we tell for Expression Comparer to compare optimized Association expressions // definedQueryMethod = (LambdaExpression)builder.AddQueryableMemberAccessors(onMember, builder.DataContext, (mi, dc) => { var queryLambda = association.GetQueryMethod(parentType, objectType) ?? throw new InvalidOperationException(); var optimizationContext = new ExpressionTreeOptimizationContext(dc); var optimizedExpr = optimizationContext.ExposeExpression(queryLambda); optimizedExpr = optimizationContext.ExpandQueryableMethods(optimizedExpr); optimizedExpr = optimizedExpr.OptimizeExpression() !; return(optimizedExpr); }); cacheCheckAdded = true; var parameterMatch = new Dictionary <ParameterExpression, Expression>(); if (onMember.Arguments == null) { if (definedQueryMethod.Parameters.Count > 1 && typeof(IDataContext).IsSameOrParentOf(definedQueryMethod.Parameters[1].Type)) { parameterMatch.Add(definedQueryMethod.Parameters[1], dataContextConstant); } } else { var definedCount = definedQueryMethod.Parameters.Count; var argumentsCount = onMember.Arguments.Count; var diff = definedCount - argumentsCount; for (int i = definedCount - 1; i >= diff; i--) { parameterMatch.Add(definedQueryMethod.Parameters[i], onMember.Arguments[i - diff]); } } var body = definedQueryMethod.Body.Transform(e => { if (e.NodeType == ExpressionType.Parameter && parameterMatch.TryGetValue((ParameterExpression)e, out var newExpression)) { return(newExpression); } return(e); }); definedQueryMethod = Expression.Lambda(body, definedQueryMethod.Parameters[0]); } var shouldAddDefaultIfEmpty = enforceDefault; if (definedQueryMethod == null) { var parentParam = Expression.Parameter(parentType, "parent"); var childParam = Expression.Parameter(objectType, association.AliasName); var parentAccessor = TypeAccessor.GetAccessor(parentType); var childAccessor = TypeAccessor.GetAccessor(objectType); Expression?predicate = null; for (var i = 0; i < association.ThisKey.Length; i++) { var parentName = association.ThisKey[i]; var parentMember = parentAccessor.Members.Find(m => m.MemberInfo.Name == parentName); if (parentMember == null) { throw new LinqException("Association key '{0}' not found for type '{1}.", parentName, parentType); } var childName = association.OtherKey[i]; var childMember = childAccessor.Members.Find(m => m.MemberInfo.Name == childName); if (childMember == null) { throw new LinqException("Association key '{0}' not found for type '{1}.", childName, objectType); } var current = ExpressionBuilder.Equal(builder.MappingSchema, Expression.MakeMemberAccess(parentParam, parentMember.MemberInfo), Expression.MakeMemberAccess(childParam, childMember.MemberInfo)); predicate = predicate == null ? current : Expression.AndAlso(predicate, current); } var expressionPredicate = association.GetPredicate(parentType, objectType); if (expressionPredicate != null) { shouldAddDefaultIfEmpty = true; shouldAddCacheCheck = true; var replacedBody = expressionPredicate.GetBody(parentParam, childParam); predicate = predicate == null ? replacedBody : Expression.AndAlso(predicate, replacedBody); } if (predicate == null) { throw new LinqException("Can not generate Association predicate"); } if (inline && !shouldAddDefaultIfEmpty) { var ed = builder.MappingSchema.GetEntityDescriptor(objectType); if (ed.QueryFilterFunc != null) { shouldAddDefaultIfEmpty = true; shouldAddCacheCheck = true; } } var queryParam = Expression.Call(Methods.LinqToDB.GetTable.MakeGenericMethod(objectType), dataContextConstant); var filterLambda = Expression.Lambda(predicate, childParam); Expression body = Expression.Call(Methods.Queryable.Where.MakeGenericMethod(objectType), queryParam, filterLambda); definedQueryMethod = Expression.Lambda(body, parentParam); } else { shouldAddDefaultIfEmpty = true; var bodyExpression = definedQueryMethod.Body.Unwrap(); if (bodyExpression.NodeType == ExpressionType.Call) { var mc = (MethodCallExpression)bodyExpression; if (mc.IsSameGenericMethod(Methods.Queryable.DefaultIfEmpty, Methods.Queryable.DefaultIfEmptyValue)) { shouldAddDefaultIfEmpty = false; } } } if (!cacheCheckAdded && shouldAddCacheCheck) { // here we tell for Expression Comparer to compare optimized Association expressions // var closureExpr = definedQueryMethod; definedQueryMethod = (LambdaExpression)builder.AddQueryableMemberAccessors(onMember, builder.DataContext, (mi, dc) => { var optimizationContext = new ExpressionTreeOptimizationContext(dc); var optimizedExpr = optimizationContext.ExposeExpression(closureExpr); optimizedExpr = optimizationContext.ExpandQueryableMethods(optimizedExpr); optimizedExpr = optimizedExpr.OptimizeExpression() !; return(optimizedExpr); }); } if (loadWith != null) { var associationLoadWith = GetLoadWith(loadWith)? .FirstOrDefault(li => li.Info.MemberInfo == association.MemberInfo); if (associationLoadWith != null && (associationLoadWith.Info.MemberFilter != null || associationLoadWith.Info.FilterFunc != null)) { var body = definedQueryMethod.Body.Unwrap(); var memberFilter = associationLoadWith.Info.MemberFilter; if (memberFilter != null) { var elementType = EagerLoading.GetEnumerableElementType(memberFilter.Parameters[0].Type, builder.MappingSchema); var filtered = Expression.Convert(body, typeof(IEnumerable <>).MakeGenericType(elementType)); var filterBody = memberFilter.GetBody(filtered); body = Expression.Call( Methods.Enumerable.AsQueryable.MakeGenericMethod(objectType), filterBody); } var loadWithFunc = associationLoadWith.Info.FilterFunc; if (loadWithFunc != null) { loadWithFunc = loadWithFunc.Unwrap(); if (loadWithFunc is LambdaExpression lambda) { body = lambda.GetBody(body); } else { var filterDelegate = loadWithFunc.EvaluateExpression <Delegate>() ?? throw new LinqException("Cannot convert filter function '{loadWithFunc}' to Delegate."); var arumentType = filterDelegate.GetType().GetGenericArguments()[0].GetGenericArguments()[0]; // check for fake argument q => q if (arumentType.IsSameOrParentOf(objectType)) { var query = ExpressionQueryImpl.CreateQuery(objectType, builder.DataContext, body); var filtered = (IQueryable)filterDelegate.DynamicInvoke(query) !; body = filtered.Expression; } } } definedQueryMethod = Expression.Lambda(body, definedQueryMethod.Parameters); } if (associationLoadWith?.NextLoadWith != null && associationLoadWith.NextLoadWith.Count > 0) { definedQueryMethod = (LambdaExpression)EnrichTablesWithLoadWith(builder.DataContext, definedQueryMethod, objectType, associationLoadWith.NextLoadWith, builder.MappingSchema); } } if (parentOriginalType != parentType) { // add discriminator filter var ed = builder.MappingSchema.GetEntityDescriptor(parentOriginalType); foreach (var inheritanceMapping in ed.InheritanceMapping) { if (inheritanceMapping.Type == parentType) { var objParam = Expression.Parameter(objectType, "o"); var filterLambda = Expression.Lambda(ExpressionBuilder.Equal(builder.MappingSchema, Expression.MakeMemberAccess(definedQueryMethod.Parameters[0], inheritanceMapping.Discriminator.MemberInfo), Expression.Constant(inheritanceMapping.Code)), objParam); var body = definedQueryMethod.Body.Unwrap(); body = Expression.Call(Methods.Queryable.Where.MakeGenericMethod(objectType), body, filterLambda); definedQueryMethod = Expression.Lambda(body, definedQueryMethod.Parameters); shouldAddDefaultIfEmpty = true; break; } } } if (inline && shouldAddDefaultIfEmpty) { var body = definedQueryMethod.Body.Unwrap(); body = Expression.Call(Methods.Queryable.DefaultIfEmpty.MakeGenericMethod(objectType), body); definedQueryMethod = Expression.Lambda(body, definedQueryMethod.Parameters); isLeft = true; } else { isLeft = false; } definedQueryMethod = (LambdaExpression)builder.ConvertExpressionTree(definedQueryMethod); definedQueryMethod = (LambdaExpression)builder.ConvertExpression(definedQueryMethod); definedQueryMethod = (LambdaExpression)definedQueryMethod.OptimizeExpression() !; return(definedQueryMethod); }
public bool IsMatch(string template, PathString action, HttpContext httpContext, AccessorMember method, out RouteValueDictionary values) { if (template == null) { values = default; return(string.IsNullOrWhiteSpace(action)); } if (template.Equals(action, StringComparison.OrdinalIgnoreCase)) { values = default; return(true); } if (!Templates.TryGetValue(template, out var parsed)) { Templates.Add(template, parsed = TemplateParser.Parse(template)); } if (!Defaults.TryGetValue(template, out var defaults)) { Defaults.Add(template, defaults = GetDefaultParameters(parsed)); } if (!Matchers.TryGetValue(template, out var matcher)) { Matchers.Add(template, matcher = new TemplateMatcher(parsed, defaults)); } values = new RouteValueDictionary(); if (!matcher.TryMatch(action, values)) { return(false); } var constraints = method.Attributes.OfType <IActionConstraint>().OrderBy(x => x.Order).AsList(); if (constraints.Count > 0) { var context = new ActionConstraintContext { RouteContext = new RouteContext(httpContext) }; foreach (var constraint in constraints) { if (!constraint.Accept(context)) { return(false); } } } return(true); }
private void IndexMember(IDbConnection db, IDbTransaction t, int revision, AccessorMember member, bool unique) { var sql = SqliteBuilder.CreateIndexSql(GetResourceName(), member.Name, revision, unique); db.Execute(sql, transaction: t); }
// Returns // (ParentType p) => dc.GetTable<ObjectType>().Where(...) // (ParentType p) => dc.GetTable<ObjectType>().Where(...).DefaultIfEmpty public static LambdaExpression CreateAssociationQueryLambda(ExpressionBuilder builder, AccessorMember onMember, AssociationDescriptor association, Type parentOriginalType, Type parentType, Type objectType, bool inline, bool enforceDefault, List <LoadWithInfo[]>?loadWith, out bool isLeft) { var dataContextConstant = Expression.Constant(builder.DataContext, builder.DataContext.GetType()); // We are trying to keep fast cache hit behaviour, so cache check should be added only if needed // bool shouldAddCacheCheck = false; bool cacheCheckAdded = false; LambdaExpression?definedQueryMethod = null; if (association.HasQueryMethod()) { // here we tell for Expression Comparer to compare optimized Association expressions // definedQueryMethod = (LambdaExpression)builder.AddQueryableMemberAccessors((association, parentType, objectType), onMember, builder.DataContext, static (context, mi, dc) =>
private static bool IsNumber(AccessorMember member) { return(member.Type == typeof(int)); }
public bool IsIgnored(AccessorMember member) { return(member.HasAttribute <NotMappedAttribute>()); }
private static string GetClusterColor(AccessorMember member) { return(member.TryGetAttribute(out ColorAttribute color) ? color.Color.ToRgbaHexString() : "blue"); }
private static object ResolveValue(object @object, IEnumerable <IFieldTransform> transforms, IReadAccessor accessor, AccessorMember v) { foreach (var field in transforms) { if (field.TryTransform(accessor, @object, v, out var transformed)) { return(transformed); } } accessor.TryGetValue(@object, v.Name, out var untransformed); return(untransformed); }
private static bool IsSaved(IDataInfoProvider provider, AccessorMember member) => provider == null || provider.IsSaved(member);
private static bool IsChildResource(AccessorMember x) { // other resources return(typeof(IResource).IsAssignableFrom(x.Type)); }
private static bool IsValueCollection(AccessorMember x) { return(x.Type == typeof(byte[]) || x.Type == typeof(string)); }