internal static bool InternalCanDuckAs( Type type, Type toType, bool allowFuzzy, // ReSharper disable once UnusedParameter.Global // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Global bool throwIfNotAllowed ) { if (ConverterLocator.HaveConverterFor(type, toType)) { return(true); } var errors = GetDuckErrorsFor(type, toType, allowFuzzy); if (throwIfNotAllowed && errors.Any()) { throw new UnDuckableException(errors); } return(!errors.Any()); }
private static bool MatchesTypeOrCanConvert(PropertyInfo needle, PropertyInfo matchByName) { return(matchByName.PropertyType == needle.PropertyType || ConverterLocator.HaveConverterFor(matchByName.PropertyType, needle.PropertyType) || EnumConverter.CanPerhapsConvertBetween(matchByName.PropertyType, needle.PropertyType)); }
// TODO: should be moved out into a shared location & used at duck-type // to prevent erroneous ducks private bool NonVoidFunctionAccepts( object value, object[] arguments, out Type[] parameterTypes, out Type returnType ) { parameterTypes = null; returnType = null; var funcType = value.GetType(); if (!funcType.IsGenericType) { return(false); } var parameterCount = Array.IndexOf(FuncGenerics, funcType.GetGenericTypeDefinition()); if (parameterCount != arguments.Length) { if (parameterCount > FuncGenerics.Length) { throw new NotSupportedException( $"methods with more than {FuncGenerics.Length} parameters are not supported"); } return(false); } var genericParameters = funcType.GetGenericArguments(); parameterTypes = genericParameters.Take(genericParameters.Length - 1).ToArray(); returnType = genericParameters.Last(); var zipped = arguments.Zip( parameterTypes, (argument, parameterType) => new { argumentType = argument?.GetType(), parameterType } ); return(zipped.Aggregate( true, (acc, cur) => { if (!acc) { return false; } if (cur.argumentType is null && cur.parameterType.IsNullableType()) { return true; } if (cur.argumentType.IsAssignableOrUpCastableTo(cur.parameterType)) { return true; } return cur.argumentType == cur.parameterType || ConverterLocator.HaveConverterFor(cur.argumentType, cur.parameterType); }));