private static Maybe <EntityConvertorArgs> SetPropertyValue( [NotNull] PropertyInfo argPropertyInfo, [NotNull] string arg, [NotNull] EntityConvertorArgs typedArgs) { var argType = argPropertyInfo.GetGetMethod().ReturnType; try { if (!argType.IsArray) { ArgsPropertySettersMap.GetValue(argType) .Do(argsSetter => argsSetter(argPropertyInfo, arg, typedArgs), () => argPropertyInfo.SetValue(typedArgs, Convert.ChangeType(arg, argType))); } else { var mayBeArray = ParseArray(arg, argType); if (!mayBeArray.HasValue) { return(Maybe <EntityConvertorArgs> .Nothing); } argPropertyInfo.SetValue(typedArgs, mayBeArray.Value); } } catch (Exception ex) { Console.Error.WriteLine($"{arg} is not a valid {argType.Name} argument. {ex.Message}"); return(Maybe <EntityConvertorArgs> .Nothing); } return(typedArgs); }
public static Maybe <EntityConvertorArgs> ParseCommandLine([NotNull][ItemNotNull] string[] args) { // (Key + value) * args.count if (args.Length != SupportedArgs.Value.Length * 2) { return(Maybe <EntityConvertorArgs> .Nothing); } var typedArgs = new EntityConvertorArgs(); var supportedArgs = SupportedArgs.Value; PropertyInfo expectedArgPropertyInfo = null; var passedArgPropertyInfos = new HashSet <PropertyInfo>(); foreach (var arg in args) { var argMeta = supportedArgs.FirstOrDefault(supportedArg => supportedArg.Attribute.Keys.Contains(arg)); if (expectedArgPropertyInfo != null) { if (argMeta != null) { // Key in place of value. return(Maybe <EntityConvertorArgs> .Nothing); } var mayBeTypedArgs = SetPropertyValue(expectedArgPropertyInfo, arg.Trim(), typedArgs); if (!mayBeTypedArgs.HasValue) { // Can't set key by value, incorrect value. return(Maybe <EntityConvertorArgs> .Nothing); } typedArgs = mayBeTypedArgs.Value; expectedArgPropertyInfo = null; } else { // Unknown key. if (argMeta == null) { return(Maybe <EntityConvertorArgs> .Nothing); } expectedArgPropertyInfo = argMeta.PropertyInfo; passedArgPropertyInfos.Add(expectedArgPropertyInfo); } } // Not all args are passed. if (passedArgPropertyInfos.Count != SupportedArgs.Value.Length) { return(Maybe <EntityConvertorArgs> .Nothing); } return(typedArgs); }
private static Uri CreateConversionEndpointUri([NotNull] EntityConvertorArgs args) { const string convertGeneralToTypeEndpointPath = "PageServices/ActionsService.asmx/ConvertGeneralToType"; const string authenticationTokenParamTemplate = "?access_token={0}"; string authenticatedConvertGeneralToTypeEndpointPath = $"{convertGeneralToTypeEndpointPath}{string.Format(authenticationTokenParamTemplate, args.AccessToken)}"; return(new Uri(args.InstanceUri, authenticatedConvertGeneralToTypeEndpointPath)); }
private static int PerformConversionGeneralToType([NotNull] EntityConvertorArgs args) { // Targetprocess enforces TLS 1.2 On-Demand, so add this to supported security protocols. // https://www.targetprocess.com/blog/2016/03/targetprocess-will-start-enforcing-tls-1-2-encryption/ ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; // When you want to use C# 7.0 value tuple, for .NET 4.6.2 or lower, .NET Core 1.x, and .NET Standard 1.x // you need to install the NuGet package System.ValueTuple. var conversions = new List <(int GeneralId, Task <HttpResponseMessage> ConversionTask)>(args.GeneralIdsToConvert.Count()); var serializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; using (var httpClient = new HttpClient()) { Uri conversionEndpointUri = CreateConversionEndpointUri(args); // Try run conversions in parallel to reduce overall time. foreach (var generalIdToConvert in args.GeneralIdsToConvert) { var convertDto = new ConvertGeneralToTypeDto { EntityTypeId = args.EntityKindId, GeneralId = generalIdToConvert }; var conversionRequest = CreateConversionRequest(convertDto, serializerSettings); var conversionTask = httpClient.PostAsync(conversionEndpointUri, conversionRequest); conversions.Add((generalIdToConvert, conversionTask)); } var waitTimeout = args.WaitTimeout; try { bool areAllConversionsDone = Task.WaitAll(conversions.Select(conversion => conversion.ConversionTask).ToArray <Task>(), waitTimeout); if (!areAllConversionsDone) { throw new TimeoutException($"Conversion is not completed in {waitTimeout}, ending coversion."); } } catch (AggregateException ex) { Console.Error.WriteLine(ex.Flatten()); return(ErrorCodes.ConvertError); } catch (TimeoutException ex) { Console.Error.WriteLine(ex); return(ErrorCodes.ConvertError); } } var conversionErrors = conversions .Where(conversion => !conversion.ConversionTask.Result.IsSuccessStatusCode) .Select(conversion => { var conversionTaskResponse = conversion.ConversionTask.Result; var body = conversionTaskResponse.Content.ToString(); return($"Error during conversion of general with id {conversion.GeneralId}.{Environment.NewLine}" + $"Status code: {conversionTaskResponse.StatusCode}, Body: {body}" + $"{Environment.NewLine}"); }) .ToList(); if (conversionErrors.Count == 0) { Console.WriteLine($"All generals with ids {string.Join(", ", args.GeneralIdsToConvert)} " + "are converted successfully."); return(ErrorCodes.Ok); } conversionErrors.ForEach(conversionError => Console.Error.WriteLine(conversionError)); return(ErrorCodes.ConvertError); }