Beispiel #1
0
        private static bool IsEquivalentAsyncTypeBaseCase(
            Type syncType,
            Type asyncType,
            EquivalentTypeMatch typeMatch)
        {
            if (syncType == asyncType)
            {
                return(true);
            }

            if (typeMatch == EquivalentTypeMatch.AllowMoreSpecificAsyncType && asyncType.IsAssignableTo(syncType))
            {
                return(true);
            }

            if (typeMatch == EquivalentTypeMatch.AllowMoreSpecificSyncType && syncType.IsAssignableTo(asyncType))
            {
                return(true);
            }

            return(false);
        }
Beispiel #2
0
        public static bool IsEquivalentAsyncType(
            Type syncType,
            Type asyncType,
            EquivalentTypeMatch typeMatch = EquivalentTypeMatch.ExactMatch)
        {
            if (IsEquivalentAsyncTypeBaseCase(syncType, asyncType, typeMatch))
            {
                return(true);
            }

            Type?syncElementType, asyncElementType;

            if (TypeHelper.IsGroupingType(syncType, out var syncKeyType, out syncElementType) &&
                TypeHelper.IsAsyncGroupingType(asyncType, out var asyncKeyType, out asyncElementType))
            {
                if (IsEquivalentAsyncType(syncElementType, asyncElementType, typeMatch) &&
                    IsEquivalentAsyncType(syncKeyType, asyncKeyType, typeMatch))
                {
                    return(true);
                }
            }

            if (TypeHelper.IsQueryableType(syncType, allowNonGeneric: true, out syncElementType))
            {
                if (TypeHelper.IsAsyncQueryableType(asyncType, allowNonGeneric: true, out asyncElementType))
                {
                    if (IsEquivalentAsyncType(syncElementType, asyncElementType, typeMatch))
                    {
                        return(true);
                    }
                }
                else if (typeMatch == EquivalentTypeMatch.AllowMoreSpecificSyncType &&
                         TypeHelper.IsAsyncEnumerableType(asyncType, out asyncElementType))
                {
                    if (IsEquivalentAsyncType(syncElementType, asyncElementType, typeMatch))
                    {
                        return(true);
                    }
                }
            }

            if (TypeHelper.IsEnumerableType(syncType, allowNonGeneric: true, out syncElementType))
            {
                if (TypeHelper.IsAsyncEnumerableType(asyncType, out asyncElementType))
                {
                    if (IsEquivalentAsyncType(syncElementType, asyncElementType, typeMatch))
                    {
                        return(true);
                    }
                }
                else if (typeMatch == EquivalentTypeMatch.AllowMoreSpecificAsyncType &&
                         TypeHelper.IsAsyncQueryableType(asyncType, allowNonGeneric: true, out asyncElementType))
                {
                    if (IsEquivalentAsyncType(syncElementType, asyncElementType, typeMatch))
                    {
                        return(true);
                    }
                }
            }

            if (TypeHelper.IsValueTaskType(asyncType, out var resultType))
            {
                if (IsEquivalentAsyncType(syncType, resultType, typeMatch))
                {
                    return(true);
                }
            }

            return(IsEquivalentLambdaExpressionType(syncType, asyncType, typeMatch));
        }
Beispiel #3
0
        private static bool IsEquivalentLambdaExpressionType(
            Type syncType,
            Type asyncType,
            EquivalentTypeMatch typeMatch)
        {
            if (!TypeHelper.IsLambdaExpression(syncType, out var syncDelegateType))
            {
                if (typeMatch == EquivalentTypeMatch.AllowMoreSpecificAsyncType && TypeHelper.IsDelegate(syncType))
                {
                    syncDelegateType = syncType;
                }
                else
                {
                    return(false);
                }
            }

            if (!TypeHelper.IsLambdaExpression(asyncType, out var asyncDelegateType))
            {
                if (typeMatch == EquivalentTypeMatch.AllowMoreSpecificSyncType && TypeHelper.IsDelegate(asyncType))
                {
                    asyncDelegateType = asyncType;
                }
                else
                {
                    return(false);
                }
            }

            var syncMethod  = syncDelegateType.GetMethod("Invoke") !;
            var asyncMethod = asyncDelegateType.GetMethod("Invoke") !;

            if (!IsEquivalentAsyncType(syncMethod.ReturnType, asyncMethod.ReturnType, typeMatch))
            {
                return(false);
            }

            var syncParameters  = syncMethod.GetParameters();
            var asyncParameters = asyncMethod.GetParameters();

            if (syncParameters.Length != asyncParameters.Length)
            {
                if (asyncParameters.Length != syncParameters.Length + 1 ||
                    asyncParameters[^ 1].ParameterType != typeof(CancellationToken))
                {
                    return(false);
                }
            }

            var parameterTypeMatch = typeMatch switch
            {
                EquivalentTypeMatch.AllowMoreSpecificAsyncType => EquivalentTypeMatch.AllowMoreSpecificSyncType,
                EquivalentTypeMatch.AllowMoreSpecificSyncType => EquivalentTypeMatch.AllowMoreSpecificAsyncType,
                _ => EquivalentTypeMatch.ExactMatch,
            };

            for (var i = 0; i < syncParameters.Length; i++)
            {
                var parameterIsEquivalent = IsEquivalentAsyncType(
                    syncParameters[i].ParameterType,
                    asyncParameters[i].ParameterType,
                    parameterTypeMatch);

                if (!parameterIsEquivalent)
                {
                    return(false);
                }
            }

            return(true);
        }