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); }
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)); }
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); }