public AphidInteropMethodArg(object argument, ParameterInfoCache parameterInfo) : this(argument, parameterInfo, constructsParamArray : null) { }
private AphidInteropMethodArg( ParameterInfo parameter, object argument, bool?constructsParamArray = null) { Argument = argument; if (argument != null) { ArgumentType = argument.GetType(); lock (ParamCache) { if (!ParamCache.TryGetValue(parameter, out _paramInfo)) { ParamCache.Add( parameter, _paramInfo = new ParameterInfoCache(parameter, ArgumentType)); _argInfo = _paramInfo.InitialArgumentTypeCache; } else if (!_paramInfo.ArgumentTypeCache.TryGetValue(ArgumentType, out _argInfo)) { _paramInfo.ArgumentTypeCache.Add( ArgumentType, _argInfo = new ArgumentTypeCache( ArgumentType, _paramInfo, _paramInfo.TargetType)); } } } else { lock (ParamCache) { if (!ParamCache.TryGetValue(parameter, out _paramInfo)) { ParamCache.Add( parameter, _paramInfo = new ParameterInfoCache(parameter)); } _argInfo = new ArgumentTypeCache(); } } IsGeneric = TargetType.IsGenericType; if (_argInfo.NeedsStringToCharCheck) { if (((string)Argument).Length == 1) { IsExactBasicTypeMatch = true; } //IsExactUserReferenceTypeMatch = false; } else if (_argInfo.NeedsDecimalFitCheck) { IsConvertibleNumberPair = AphidTypeConverter.CanConvertDecimal( (decimal)Argument, TargetType); } else { IsConvertibleNumberPair = _argInfo.IsConvertibleNumberPair; IsExactBasicTypeMatch = _argInfo.IsExactBasicTypeMatch; IsExactUserReferenceTypeMatch = _argInfo.IsExactUserReferenceTypeMatch; } if (HasParamArray) { if (constructsParamArray == null) { if (!HasParamArray) { ConstructsParamArray = false; PassesParamArray = false; } else { if (!IsExactTypeMatch && ArgumentType?.GetInterface("IEnumerable") != null) { ConstructsParamArray = true; PassesParamArray = false; } else { ConstructsParamArray = false; PassesParamArray = true; } } } else { ConstructsParamArray = constructsParamArray.Value; PassesParamArray = !ConstructsParamArray; } } }
public ArgumentTypeCache( Type argumentType, ParameterInfoCache targetParam, Type targetType) { if (IsExactTypeMatch = argumentType == targetType) { IsExactBasicTypeMatch = argumentType.IsPrimitive || argumentType.IsEnum || argumentType == typeof(string) || argumentType == typeof(decimal); IsExactUserReferenceTypeMatch = argumentType.IsClass && argumentType != typeof(object); HasToStringConversion = targetType == typeof(string); } else if (argumentType == typeof(string) && targetType == typeof(char[])) { IsExactBasicTypeMatch = false; IsExactUserReferenceTypeMatch = false; HasToStringConversion = targetType == typeof(string); } else if (argumentType == typeof(char) && targetType == typeof(string)) { IsExactBasicTypeMatch = true; IsExactUserReferenceTypeMatch = false; HasToStringConversion = targetType == typeof(string); } else if (argumentType != typeof(string) || targetType != typeof(char)) { if ((ImplicitConversionOperator = ConversionOperator.GetImplicitOperator( targetType, argumentType)) != null) { HasImplicitConversion = true; } else if ((ExplicitConversionOperator = ConversionOperator.GetExplicitOperator( targetType, argumentType)) != null) { HasExplicitConversion = true; } if (targetType == typeof(string)) { HasToStringConversion = true; } IsExactBasicTypeMatch = IsExactUserReferenceTypeMatch = false; } else { HasToStringConversion = targetType == typeof(string); NeedsStringToCharCheck = true; } IsDerivedFromUserReferenceType = targetParam.IsClass && targetType != typeof(object) && targetType != typeof(object[]) && (argumentType == null || (argumentType.IsClass && argumentType.IsDerivedFrom(targetType))); IsNonRootImplementationOfTarget = targetType.IsInterface && argumentType != null && argumentType != typeof(object) && argumentType.GetInterfaces().Contains(targetType); if (argumentType == typeof(decimal) && AphidTypeConverter.IsNumber(targetType)) { NeedsDecimalFitCheck = true; IsPrecisionLost = targetType == typeof(float) || targetType == typeof(double); } else if (targetType == typeof(decimal) && AphidTypeConverter.IsNumber(argumentType)) { IsConvertibleNumberPair = true; } else { // Todo: cover non-decimal to non-decimal checks e.g. // ulong to uint -> uint.MinValue <= ulongValue && ulongValue <= uint.MaxValue IsConvertibleNumberPair = false; } }