public static void Deserialize_serializedString_type___Should_deserialize_DateTime___When_called()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            // note that this will return "+00:00" if machine is on UTC time, which is what we expect
            var offset = DateTime.Now.ToString("%K");

            var scenarios = new List <(DateTime Expected, string SerializedString)>
            {
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Utc), "2019-01-05T12:14:58.1920000Z"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Utc).AddTicks(1), "2019-01-05T12:14:58.1920001Z"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Utc).AddTicks(20), "2019-01-05T12:14:58.1920020Z"),

                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Unspecified), "2019-01-05T12:14:58.1920000"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Unspecified).AddTicks(1), "2019-01-05T12:14:58.1920001"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Unspecified).AddTicks(20), "2019-01-05T12:14:58.1920020"),

                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Local), "2019-01-05T12:14:58.1920000" + offset),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Local).AddTicks(1), "2019-01-05T12:14:58.1920001" + offset),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Local).AddTicks(20), "2019-01-05T12:14:58.1920020" + offset),
            };

            // Act
            var actuals = scenarios.Select(_ => (DateTime)systemUnderTest.Deserialize(_.SerializedString, typeof(DateTime))).ToList();

            // Assert
            actuals.Must().BeEqualTo(scenarios.Select(_ => _.Expected).ToList());
        }
        public static void SerializeToString_DateTime___Should_return_serialized_string_representation_of_value_for_different_DateTimeKind___When_called()
        {
            // Arrange

            // note that this will return "+00:00" if machine is on UTC time, which is what we expect
            var offset = DateTime.Now.ToString("%K");

            var scenarios = new List <(DateTime Value, string Expected)>
            {
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Utc), "2019-01-05T12:14:58.1920000Z"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Utc).AddTicks(1), "2019-01-05T12:14:58.1920001Z"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Utc).AddTicks(20), "2019-01-05T12:14:58.1920020Z"),

                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Unspecified), "2019-01-05T12:14:58.1920000"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Unspecified).AddTicks(1), "2019-01-05T12:14:58.1920001"),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Unspecified).AddTicks(20), "2019-01-05T12:14:58.1920020"),

                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Local), "2019-01-05T12:14:58.1920000" + offset),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Local).AddTicks(1), "2019-01-05T12:14:58.1920001" + offset),
                (new DateTime(2019, 1, 5, 12, 14, 58, 192, DateTimeKind.Local).AddTicks(20), "2019-01-05T12:14:58.1920020" + offset),
            };

            // Act
            var actuals = scenarios.Select(_ => ObcDateTimeStringSerializer.SerializeToString(_.Value)).ToList();

            // Assert
            actuals.Must().BeEqualTo(scenarios.Select(_ => _.Expected).ToList());
        }
        public static void Deserialize_serializedString_type___Should_deserialize_UTC_DateTime___When_serialized_strings_have_reduced_precision()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            var serializedDateTimes = new[]
            {
                "2017-05-06T02:28:46.2704883Z",
                "2017-05-06T02:28:46.270484Z",
                "2017-05-06T02:28:46.27048Z",
                "2017-05-06T02:28:46.2704Z",
                "2017-05-06T02:28:46.271Z",
                "2017-05-06T02:28:46.27Z",
                "2017-05-06T02:28:46.2Z",
                "2017-05-06T02:28:46Z",
                "2017-05-06T02:28:00Z",
                "2017-05-06T02:00:00Z",
                "2017-05-06T00:00:00Z",
            };

            var expected = serializedDateTimes.Select(_ => DateTime.Parse(_, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)).ToList();

            // Act
            var actual = serializedDateTimes.Select(_ => (DateTime)systemUnderTest.Deserialize(_, typeof(DateTime))).ToList();

            // Assert
            actual.Must().BeEqualTo(expected);
        }
        public static void DeserializeToDateTime___Should_throw_InvalidOperationException___When_serializedString_is_malformed()
        {
            // Arrange
            var serializedDateTimes = new[]
            {
                "2017-05-06T02:28:46",                // no precision not supported for Unspecified
                "2017-05-06T02:28:46+00:00",          // no precision not supported for Local
                "2017-05-06T02:28:46.270488",         // less than 7 precision not supported for Unspecified
                "2017-05-06T02:28:46.270488+00:00",   // less than 7 precision not supported for Local
                "2017-05-06T02:28:46.27048838",       // too much precision
                "2017-05-06T02:28:46.27048838+00:00", // too much precision
                "2017-05-06T02:28:46.27048838Z",      // too much precision
                "2017-05-06T02:28:46.2704883K",       // shouldn't end in K
                "some-string",                        // random string
                "2017-05-06",                         // only date
                "2017-05-06+00:00",                   // only date
                "2017-05-06Z",                        // only date
                "02:28:46.1938283",                   // only time
                "02:28:46.1938283+00:00",             // only time
                "02:28:46.1938283Z",                  // only time
            };

            // Act
            var actuals = serializedDateTimes.Select(_ => Record.Exception(() => ObcDateTimeStringSerializer.DeserializeToDateTime(_))).ToList();

            // Assert
            actuals.Must().Each().BeOfType <InvalidOperationException>();
            actuals.Select(_ => _.Message).Must().Each().ContainString("is malformed; it's not in a supported format and cannot be deserialized.");
        }
        public static void DeserializeToDateTime___Should_throw_ArgumentNullException___When_parameter_serializedString_is_null()
        {
            // Arrange, Act
            var actual = Record.Exception(() => ObcDateTimeStringSerializer.DeserializeToDateTime(null));

            // Assert
            actual.Must().BeOfType <ArgumentNullException>();
            actual.Message.Must().ContainString("serializedString");
        }
        public static void DeserializeToDateTime___Should_throw_ArgumentException___When_parameter_serializedString_is_white_space()
        {
            // Arrange, Act
            var actual = Record.Exception(() => ObcDateTimeStringSerializer.DeserializeToDateTime(Invariant($"  {Environment.NewLine} ")));

            // Assert
            actual.Must().BeOfType <ArgumentException>();
            actual.Message.Must().ContainString("serializedString");
            actual.Message.Must().ContainString("white space");
        }
        private string MakeStringFromObject(
            object value)
        {
            if (value == null)
            {
                return(null);
            }

            var propertyType = value.GetType();

            if (this.configuredTypeToSerializerMap.ContainsKey(propertyType))
            {
                var serializer = this.configuredTypeToSerializerMap[propertyType];

                var result = serializer.SerializeToString(value);

                return(result);
            }
            else if (value is DateTime propertyValueAsDateTime)
            {
                var result = ObcDateTimeStringSerializer.SerializeToString(propertyValueAsDateTime);

                return(result);
            }
            else
            {
                string result;

                if ((propertyType != typeof(string)) && (value is IEnumerable propertyValueAsEnumerable))
                {
                    var values = new List <string>();

                    foreach (var element in propertyValueAsEnumerable)
                    {
                        var serializedItem = this.MakeStringFromObject(element);

                        values.Add(serializedItem);
                    }

                    result = values.ToCsv(this.dictionaryStringSerializer.NullValueEncoding);
                }
                else if (value is ISerializeToString propertyValueAsSerializeToString)
                {
                    result = propertyValueAsSerializeToString.SerializeToString();
                }
                else
                {
                    result = value.ToString();
                }

                return(result);
            }
        }
        public static void Deserialize_serializedString_type___Should_throw_ArgumentNullException___When_parameter_type_is_null()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            // Act
            var actual = Record.Exception(() => systemUnderTest.Deserialize("2019-01-05T12:14:58.1920000Z", null));

            // Assert
            actual.Must().BeOfType <ArgumentNullException>();
            actual.Message.Must().ContainString("type");
        }
        public static void Deserialize_T___Should_throw_ArgumentNullException___When_parameter_serializedString_is_null()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            // Act
            var actual = Record.Exception(() => systemUnderTest.Deserialize <DateTime>(null));

            // Assert
            actual.Must().BeOfType <ArgumentNullException>();
            actual.Message.Must().ContainString("serializedString");
        }
        public static void SerializeToString_object___Should_throw_ArgumentNullException___When_parameter_value_is_null()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            object value = null;

            // Act
            var actual = Record.Exception(() => systemUnderTest.SerializeToString(value));

            // Assert
            actual.AsTest().Must().BeOfType <ArgumentNullException>();
        }
        public static void RoundtripSerializeDeserialize___Using_local_negative_offset___Works()
        {
            // Arrange
            var expected   = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"));
            var serializer = new ObcDateTimeStringSerializer();

            // Act
            var serialized = serializer.SerializeToString(expected);
            var actual     = serializer.Deserialize <DateTime>(serialized);

            // Assert
            actual.Kind.Must().BeEqualTo(expected.Kind);
            actual.Must().BeEqualTo(expected);
        }
        public static void RoundtripSerializeDeserialize___Using_unspecified___Works()
        {
            // Arrange
            var expected   = DateTime.UtcNow.ToUnspecified();
            var serializer = new ObcDateTimeStringSerializer();

            // Act
            var serialized = serializer.SerializeToString(expected);
            var actual     = serializer.Deserialize <DateTime>(serialized);

            // Assert
            actual.Kind.Must().BeEqualTo(expected.Kind);
            actual.Must().BeEqualTo(expected);
        }
        public static void SerializeToString_object___Should_throw_ArgumentException___When_parameter_value_is_not_DateTime()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            var values = new[] { new object(), A.Dummy <string>(), A.Dummy <int>(), A.Dummy <Guid>() };

            // Act
            var actual = values.Select(_ => Record.Exception(() => systemUnderTest.SerializeToString(_))).ToList();

            // Assert
            actual.Must().Each().BeOfType <ArgumentException>();
            actual.Select(_ => _.Message).Must().Each().ContainString("objectToSerialize.GetType() != typeof(DateTime);");
        }
        public static void Deserialize_serializedString_type___Should_throw_ArgumentException___When_parameter_type_is_not_DateTime()
        {
            // Arrange
            var systemUnderTest = new ObcDateTimeStringSerializer();

            // Act
            var actual1 = Record.Exception(() => systemUnderTest.Deserialize("2019-01-05T12:14:58.1920000Z", typeof(object)));
            var actual2 = Record.Exception(() => systemUnderTest.Deserialize("2019-01-05T12:14:58.1920000Z", typeof(DateTime?)));

            // Assert
            actual1.Must().BeOfType <ArgumentException>();
            actual1.Message.Must().BeEqualTo("type != typeof(DateTime); 'type' is of type 'object'");

            actual2.Must().BeOfType <ArgumentException>();
            actual2.Message.Must().BeEqualTo("type != typeof(DateTime); 'type' is of type 'DateTime?'");
        }
        private object MakeObjectFromString(
            string value,
            Type type)
        {
            if (value == null)
            {
                return(null);
            }

            if (this.configuredTypeToSerializerMap.ContainsKey(type))
            {
                var serializer = this.configuredTypeToSerializerMap[type];

                var result = serializer.Deserialize(value, type);

                return(result);
            }
            else if (type.IsEnum)
            {
                var result = Enum.Parse(type, value);

                return(result);
            }
            else if (type.IsArray)
            {
                var arrayItemType = type.GetElementType() ?? throw new SerializationException(Invariant($"Found array type that cannot extract element type: {type}"));

                var asList = (IList)this.MakeObjectFromString(value, typeof(List <>).MakeGenericType(arrayItemType));

                var asArrayList = new ArrayList(asList);

                var result = asArrayList.ToArray(arrayItemType);

                return(result);
            }
            else if (type == typeof(DateTime) || type == typeof(DateTime?))
            {
                var result = ObcDateTimeStringSerializer.DeserializeToDateTime(value);

                return(result);
            }
            else if ((type != typeof(string)) && typeof(IEnumerable).IsAssignableFrom(type))
            {
                var itemType = type.GenericTypeArguments.SingleOrDefault() ?? throw new SerializationException(Invariant($"Found {typeof(IEnumerable)} type that cannot extract element type: {type}"));

                var stringValues = value.FromCsv(this.dictionaryStringSerializer.NullValueEncoding);

                var result = (IList)typeof(List <>).MakeGenericType(itemType).Construct();

                foreach (var stringValue in stringValues)
                {
                    var itemValue = stringValue == null
                        ? null
                        : this.MakeObjectFromString(stringValue, itemType);

                    result.Add(itemValue);
                }

                return(result);
            }
            else
            {
                var typeToSearchForParse = type;

                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    typeToSearchForParse = type.GenericTypeArguments.Single();
                }

                var parseMethod = typeToSearchForParse
                                  .GetMethodsFiltered(MemberRelationships.DeclaredOrInherited, MemberOwners.All, MemberAccessModifiers.Public)
                                  .SingleOrDefault(_ =>
                {
                    var parameters = _.GetParameters();

                    return((_.Name == "Parse") && (parameters.Length == 1) && (parameters.Single().ParameterType == typeof(string)));
                });

                var result = parseMethod == null
                    ? value
                    : parseMethod.Invoke(null, new object[] { value });

                return(result);
            }
        }
Exemple #16
0
        public static void LogError(string message)
        {
            try
            {
                var          serializedDateTimeUtcNow = ObcDateTimeStringSerializer.SerializeToString(DateTime.UtcNow);
                const ushort eventLogCharacterLimit   = 31914;

                Action <string> logToFile = localMessage =>
                {
                    var preppedForFilePathTime = serializedDateTimeUtcNow.Replace(":", "-").Replace(".", "_").Replace("T", "--");
                    var fileName = preppedForFilePathTime + "--LastDitchLoggedError.log";
                    File.WriteAllText(fileName, localMessage);
                };

                Action <string> logToEventLog = localMessage =>
                {
                    var preppedMessage = localMessage == null ? "Null Message Provided." :
                                         localMessage.Length <= eventLogCharacterLimit ? localMessage :
                                         localMessage.Substring(0, eventLogCharacterLimit);
                    using (EventLog eventLog = new EventLog("Application"))
                    {
                        eventLog.Source = "Application";
                        eventLog.WriteEntry(preppedMessage, EventLogEntryType.Error, 101, 1);
                    }
                };

                Action <string> logToConsoleOut = localMessage =>
                {
                    var preppedMessage = serializedDateTimeUtcNow + "--" + localMessage;
                    Console.Out.WriteLine(preppedMessage);
                };

                Action <string> logToConsoleError = localMessage =>
                {
                    var preppedMessage = serializedDateTimeUtcNow + "--" + localMessage;
                    Console.Error.WriteLine(preppedMessage);
                };

                Action <string> logToTraceOut = localMessage =>
                {
                    var preppedMessage = serializedDateTimeUtcNow + "--" + localMessage;
                    Trace.WriteLine(preppedMessage);
                };

                Action <string> logToTraceError = localMessage =>
                {
                    var preppedMessage = serializedDateTimeUtcNow + "--" + localMessage;
                    Trace.TraceError(preppedMessage);
                };

                IReadOnlyCollection <Action <string> > actionsToRun = new[]
                {
                    logToFile,
                    logToEventLog,
                    logToConsoleOut,
                    logToConsoleError,
                    logToTraceOut,
                    logToTraceError,
                };

                void RunActionWithExceptionSwallowing(Action <string> actionToRunWithoutAllowingExceptions, string input)
                {
                    try
                    {
                        actionToRunWithoutAllowingExceptions(input);
                    }
                    catch (Exception)
                    {
                        /* no-op */
                    }
                }

                foreach (var actionToRun in actionsToRun)
                {
                    RunActionWithExceptionSwallowing(actionToRun, message);
                }
            }
            catch (Exception)
            {
                /* no-op */
            }
        }