Exemplo n.º 1
0
        public override bool TryEvaluate(
            Type sourceType,
            string operationName,
            ParameterInfo asyncParameter,
            ParameterInfo syncParameter,
            UniqueIdentifierBuilder identifierBuilder, [NotNullWhen(true)] out ParameterPair?result)
        {
            result = null;

            var asyncParamType = asyncParameter.ParameterType;
            var syncParamType  = syncParameter.ParameterType;

            if (!TypeHelper.IsIntegratedNumericType(asyncParamType) &&
                !TypeHelper.IsNullableIntegratedNumericType(asyncParamType))
            {
                return(false);
            }

            if (!TypeHelper.IsIntegratedNumericType(syncParamType) &&
                !TypeHelper.IsNullableIntegratedNumericType(syncParamType))
            {
                return(false);
            }

            identifierBuilder.WithParameter(asyncParameter.Name !);

            var syncParamDefinition = Parameter.Default(syncParameter.Name !, async(writer, variableName) =>
            {
                await writer.WriteLineAsync($"            var {variableName} = 5;").ConfigureAwait(false);
            });

            Parameter asyncParamDefinition;

            // We only need a single variable definition
            if (asyncParamType == syncParamType)
            {
                asyncParamDefinition = syncParamDefinition;
                syncParamDefinition  = Parameter.Default(asyncParamDefinition.Name);
            }
            else
            {
                asyncParamDefinition = Parameter.Default(asyncParameter.Name !, "async", async(writer, variableName) =>
                {
                    await writer.WriteLineAsync($"            var {variableName} = 5;").ConfigureAwait(false);
                });
            }

            result = new ParameterPair(asyncParamDefinition, syncParamDefinition);
            return(true);
        }
        public override bool TryEvaluate(
            Type sourceType,
            string operationName,
            ParameterInfo asyncParameter,
            ParameterInfo syncParameter,
            UniqueIdentifierBuilder identifierBuilder, [NotNullWhen(true)] out ParameterPair?result)
        {
            result = null;

            var asyncParamType = asyncParameter.ParameterType;
            var syncParamType  = syncParameter.ParameterType;

            if (!TypeHelper.IsEqualityComparerType(asyncParamType, out var asyncComparisonType))
            {
                return(false);
            }

            if (!TypeHelper.IsEqualityComparerType(syncParamType, out var syncComparisonType))
            {
                return(false);
            }

            identifierBuilder.WithParameter(asyncParameter.Name !);

            Parameter asyncParamDefinition, syncParamDefinition;

            if (syncComparisonType == typeof(string))
            {
                syncParamDefinition = Parameter.Default(syncParameter.Name !, async(writer, variableName) =>
                {
                    await writer.WriteLineAsync($"            var {variableName} = StringComparer.Ordinal;").ConfigureAwait(false);
                });
            }
            else
            {
                syncParamDefinition = Parameter.Default(syncParameter.Name !, async(writer, variableName) =>
                {
                    await writer.WriteLineAsync($"            var {variableName} = EqualityComparer<{TypeHelper.FormatCSharpTypeName(syncComparisonType, KnownNamespaces.Namespaces)}>.Default;").ConfigureAwait(false);
                });
            }

            // We only need a single variable definition
            if (string.Equals(asyncParameter.Name, syncParameter.Name, StringComparison.Ordinal) &&
                asyncComparisonType == syncComparisonType)
            {
                asyncParamDefinition = syncParamDefinition;
                syncParamDefinition  = Parameter.Default(syncParamDefinition.Name);
            }
            else if (asyncComparisonType == typeof(string))
            {
                asyncParamDefinition = Parameter.Default(asyncParameter.Name !, async(writer, variableName) =>
                {
                    await writer.WriteLineAsync($"            var {variableName} = StringComparer.Ordinal;").ConfigureAwait(false);
                });
            }
            else
            {
                asyncParamDefinition = Parameter.Default(asyncParameter.Name !, async(writer, variableName) =>
                {
                    await writer.WriteLineAsync($"            var {variableName} = EqualityComparer<{TypeHelper.FormatCSharpTypeName(asyncComparisonType, KnownNamespaces.Namespaces)}>.Default;").ConfigureAwait(false);
                });
            }

            result = new ParameterPair(asyncParamDefinition, syncParamDefinition);
            return(true);
        }
Exemplo n.º 3
0
        public override bool TryEvaluate(
            Type sourceType,
            string operationName,
            ParameterInfo asyncParameter,
            ParameterInfo syncParameter,
            UniqueIdentifierBuilder identifierBuilder, [NotNullWhen(true)] out ParameterPair?result)
        {
            result = null;

            var asyncParamType = asyncParameter.ParameterType;
            var syncParamType  = syncParameter.ParameterType;

            var  asyncParameterIsExpression = true;
            var  syncParameterIsExpression = true;
            Type?asyncDelegateType, syncDelegateType;

            if (TypeHelper.IsDelegate(asyncParamType))
            {
                asyncDelegateType          = asyncParamType;
                asyncParameterIsExpression = false;
            }
            else if (!TypeHelper.IsLambdaExpression(asyncParamType, out asyncDelegateType))
            {
                return(false);
            }

            if (TypeHelper.IsDelegate(syncParamType))
            {
                syncDelegateType          = syncParamType;
                syncParameterIsExpression = false;
            }
            else if (!TypeHelper.IsLambdaExpression(syncParamType, out syncDelegateType))
            {
                return(false);
            }

            var singleDefinition = asyncDelegateType == syncDelegateType && asyncParameterIsExpression == syncParameterIsExpression;

            if (!TryConstructDelegateOrLambdaExpression(
                    sourceType,
                    syncDelegateType,
                    prefix: null,
                    syncParameterIsExpression,
                    syncParameter.Name !,
                    operationName,
                    singleDefinition ? identifierBuilder : null,
                    out var syncParamDefinition))
            {
                return(false);
            }

            Parameter?asyncParamDefinition;

            // We only need a single variable definition
            if (singleDefinition)
            {
                asyncParamDefinition = syncParamDefinition;
                syncParamDefinition  = Parameter.Default(asyncParamDefinition.Name);
            }
            else if (!TryConstructDelegateOrLambdaExpression(
                         sourceType,
                         asyncDelegateType,
                         prefix: "async",
                         asyncParameterIsExpression,
                         asyncParameter.Name !,
                         operationName,
                         identifierBuilder,
                         out asyncParamDefinition))
            {
                return(false);
            }

            result = new ParameterPair(asyncParamDefinition, syncParamDefinition);
            return(true);
        }
Exemplo n.º 4
0
        public override bool TryEvaluate(
            Type sourceType,
            string operationName,
            ParameterInfo asyncParameter,
            ParameterInfo syncParameter,
            UniqueIdentifierBuilder identifierBuilder, [NotNullWhen(true)] out ParameterPair?result)
        {
            result = null;

            var asyncParamType = asyncParameter.ParameterType;
            var syncParamType  = syncParameter.ParameterType;

            int?limit = null;

            // Limit the source of Single and SingleOrDefault operations, but only if there is not predicate
            if (string.Equals(operationName, "Single", StringComparison.Ordinal) ||
                string.Equals(operationName, "SingleOrDefault", StringComparison.Ordinal))
            {
                // Use the sync method, here as the async method can have a cancellation-token
                if ((syncParameter.Member as MethodInfo) !.GetParameters().Length == 1)
                {
                    limit = 1;
                }
            }

            if (TryEvaluateKnownType(
                    operationName,
                    asyncParamType,
                    syncParamType,
                    asyncParameter.Name !,
                    syncParameter.Name !,
                    identifierBuilder,
                    transform: null,
                    limit,
                    out result))
            {
                return(true);
            }

            if (typeof(IAsyncQueryable <object>).IsAssignableTo(asyncParamType) &&
                typeof(IQueryable <object>).IsAssignableTo(syncParamType))
            {
                if (string.Equals(operationName, "OfType", StringComparison.Ordinal))
                {
                    if (!string.Equals(asyncParameter.Name, "source", StringComparison.Ordinal))
                    {
                        identifierBuilder.WithParameter(asyncParameter.Name !);
                    }

                    var knownPrimitiveCollectionTypes = KnownCollectionTypes.CollectionTypes.ToArray();

                    var asyncParamDefinition = Parameter.Default(asyncParameter.Name !, "async", async(writer, variableName) =>
                    {
                        for (var i = 0; i < knownPrimitiveCollectionTypes.Length; i++)
                        {
                            await writer.WriteLineAsync($"            var {variableName}Part{i + 1} = queryAdapter.GetAsyncQueryable<{TypeHelper.FormatCSharpTypeName(knownPrimitiveCollectionTypes[i], KnownNamespaces.Namespaces)}>().Select(p => (object)p);").ConfigureAwait(false);
                        }

                        await writer.WriteAsync($"            var {variableName} = ").ConfigureAwait(false);

                        for (var i = 0; i < knownPrimitiveCollectionTypes.Length; i++)
                        {
                            if (i == 0)
                            {
                                await writer.WriteAsync($"{variableName}Part{i + 1}").ConfigureAwait(false);
                            }
                            else
                            {
                                await writer.WriteAsync($".Concat({variableName}Part{i + 1})").ConfigureAwait(false);
                            }
                        }

                        await writer.WriteLineAsync($";").ConfigureAwait(false);
                    });

                    var syncParamDefinition = Parameter.Default(syncParameter.Name !, async(writer, variableName) =>
                    {
                        for (var i = 0; i < knownPrimitiveCollectionTypes.Length; i++)
                        {
                            await writer.WriteLineAsync($"            var {variableName}Part{i + 1} = GetQueryable<{TypeHelper.FormatCSharpTypeName(knownPrimitiveCollectionTypes[i], KnownNamespaces.Namespaces)}>().Select(p => (object)p);").ConfigureAwait(false);
                        }

                        await writer.WriteAsync($"            var {variableName} = ").ConfigureAwait(false);

                        for (var i = 0; i < knownPrimitiveCollectionTypes.Length; i++)
                        {
                            if (i == 0)
                            {
                                await writer.WriteAsync($"{variableName}Part{i + 1}").ConfigureAwait(false);
                            }
                            else
                            {
                                await writer.WriteAsync($".Concat({variableName}Part{i + 1})").ConfigureAwait(false);
                            }
                        }

                        await writer.WriteLineAsync($";").ConfigureAwait(false);
                    });

                    result = new ParameterPair(asyncParamDefinition, syncParamDefinition);
                    return(true);
                }
                else if (string.Equals(operationName, "Cast", StringComparison.Ordinal))
                {
                    // Only include the type of collection that is casted to, to prevent exceptions
                    var asyncResultType = (asyncParameter.Member as MethodInfo) !.ReturnType;
                    var syncResultType  = (syncParameter.Member as MethodInfo) !.ReturnType;

                    if (TryEvaluateKnownType(
                            operationName,
                            asyncResultType,
                            syncResultType,
                            asyncParameter.Name !,
                            syncParameter.Name !,
                            identifierBuilder: null,
                            transform: "p => (object)p",
                            limit: null,
                            out result))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemplo n.º 5
0
        private bool TryEvaluateKnownType(
            string operationName,
            Type asyncParamType,
            Type syncParamType,
            string asyncParamName,
            string syncParamName,
            UniqueIdentifierBuilder?identifierBuilder,
            string?transform,
            int?limit,
            [NotNullWhen(true)] out ParameterPair?result)
        {
            result = null;

            if (!TypeHelper.IsAsyncQueryableType(asyncParamType, allowNonGeneric: true, out var asyncElementType) &&
                !TypeHelper.IsAsyncEnumerableType(asyncParamType, out asyncElementType))
            {
                return(false);
            }

            if (!TypeHelper.IsQueryableType(syncParamType, allowNonGeneric: true, out var syncElementType) &&
                !TypeHelper.IsEnumerableType(syncParamType, allowNonGeneric: true, out syncElementType))
            {
                return(false);
            }

            string?transform0 = null;

            if (string.Equals(operationName, "ToDictionary", StringComparison.Ordinal))
            {
                if (TypeHelper.IsNullableType(asyncElementType, out var underlyingType))
                {
                    transform0       = $"p => ({TypeHelper.FormatCSharpTypeName(asyncElementType, KnownNamespaces.Namespaces)})p";
                    asyncElementType = underlyingType;
                }

                if (TypeHelper.IsNullableType(syncElementType, out underlyingType))
                {
                    syncElementType = underlyingType;
                }
            }

            if (!KnownCollectionTypes.CollectionTypes.Contains(asyncElementType) ||
                !KnownCollectionTypes.CollectionTypes.Contains(syncElementType))
            {
                return(false);
            }

            if (!string.Equals(asyncParamName, "source", StringComparison.Ordinal))
            {
                identifierBuilder?.WithParameter(asyncParamName);
            }

            var asyncParamDefinition = Parameter.Default(asyncParamName, "async", async(writer, variableName) =>
            {
                var value = $"queryAdapter.GetAsyncQueryable<{TypeHelper.FormatCSharpTypeName(asyncElementType, KnownNamespaces.Namespaces)}>()";

                if (!string.IsNullOrEmpty(transform0))
                {
                    value += $".Select({transform0})";
                }

                if (!string.IsNullOrEmpty(transform))
                {
                    value += $".Select({transform})";
                }

                if (limit is not null)
                {
                    value += $".Take({limit})";
                }

                await writer.WriteLineAsync(FormatVariableDefinition(variableName, value)).ConfigureAwait(false);
            });

            var syncParamDefinition = Parameter.Default(syncParamName, async(writer, variableName) =>
            {
                var value = $"GetQueryable<{TypeHelper.FormatCSharpTypeName(syncElementType, KnownNamespaces.Namespaces)}>()";

                if (!string.IsNullOrEmpty(transform0))
                {
                    value += $".Select({transform0})";
                }

                if (!string.IsNullOrEmpty(transform))
                {
                    value += $".Select({transform})";
                }

                if (limit is not null)
                {
                    value += $".Take({limit})";
                }

                await writer.WriteLineAsync(FormatVariableDefinition(variableName, value)).ConfigureAwait(false);
            });

            result = new ParameterPair(asyncParamDefinition, syncParamDefinition);
            return(true);
        }