Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Standard/ObjectExtensions.cs
===================================================================
diff -u -r4000 -r4052
--- DamEngine/trunk/src/Deltares.DamEngine.Data/Standard/ObjectExtensions.cs (.../ObjectExtensions.cs) (revision 4000)
+++ DamEngine/trunk/src/Deltares.DamEngine.Data/Standard/ObjectExtensions.cs (.../ObjectExtensions.cs) (revision 4052)
@@ -27,421 +27,420 @@
using System.Linq;
using System.Reflection;
-namespace Deltares.DamEngine.Data.Standard
+namespace Deltares.DamEngine.Data.Standard;
+
+///
+/// Static class ObjectExtensions
+///
+public static class ObjectExtensions
{
+ public static readonly CultureInfo DefaultCulture = new CultureInfo("nl-NL");
+ private const double threshold = 0.0000001;
+
///
- /// Static class ObjectExtensions
+ /// Tests two double values for equality with a default precision of
///
- public static class ObjectExtensions
+ /// The first double value
+ /// The other double value to compare with
+ /// True when almost equal
+ public static bool AlmostEquals(this double double1, double double2)
{
- public static readonly CultureInfo DefaultCulture = new CultureInfo("nl-NL");
- private const double threshold = 0.0000001;
+ return AlmostEquals(double1, double2, threshold);
+ }
- ///
- /// Tests two double values for equality with a default precision of
- ///
- /// The first double value
- /// The other double value to compare with
- /// True when almost equal
- public static bool AlmostEquals(this double double1, double double2)
+ ///
+ /// Tests two double values for equality with a given precision
+ ///
+ /// The first double value
+ /// The other double value to compare with
+ /// The precision value
+ /// True when almost equal
+ public static bool AlmostEquals(this double double1, double double2, double precision)
+ {
+ if (double.IsNaN(double1) && double.IsNaN(double2))
{
- return AlmostEquals(double1, double2, threshold);
+ return true;
}
- ///
- /// Tests two double values for equality with a given precision
- ///
- /// The first double value
- /// The other double value to compare with
- /// The precision value
- /// True when almost equal
- public static bool AlmostEquals(this double double1, double double2, double precision)
+ if (double.IsNaN(double1) || double.IsNaN(double2))
{
- if (double.IsNaN(double1) && double.IsNaN(double2))
- {
- return true;
- }
+ return false;
+ }
- if (double.IsNaN(double1) || double.IsNaN(double2))
- {
- return false;
- }
+ return (Math.Abs(double1 - double2) <= precision);
+ }
- return (Math.Abs(double1 - double2) <= precision);
+ ///
+ /// Converts an object to another type. Also works with nullable types. The method can't.
+ ///
+ ///
+ /// Also works with nullable types and enums. The method can't do this.
+ ///
+ /// The type to converto to
+ /// The object to convert
+ /// The converted object
+ /// When is null and name="type"/> is value type and not nullable.
+ /// When an error occurs during conversion.
+ public static T ToType(this object value)
+ {
+ if (value == null)
+ {
+ ThrowIfValueType();
+
+ return default;
}
- ///
- /// Converts an object to another type. Also works with nullable types. The method can't.
- ///
- ///
- /// Also works with nullable types and enums. The method can't do this.
- ///
- /// The type to converto to
- /// The object to convert
- /// The converted object
- /// When is null and name="type"/> is value type and not nullable.
- /// When an error occurs during conversion.
- public static T ToType(this object value)
+ return (T) value.ToType(typeof(T), DefaultCulture);
+ }
+
+ ///
+ /// Converts an object to another type.
+ ///
+ ///
+ /// Also works with nullable types and enums. The method can't do this.
+ /// This method can also be used to downcast numeric values for example from string (double) value "12,0" to short 12
+ /// When trying to convert a string to double and the dutch culture is set, then this method tries to
+ /// parse the string with custom logic. Because it occures that some string are not properly
+ /// changed according to the current culture. For instance in dbf files where numeric values are stored as
+ /// strings (for example "10,23")
+ /// Use this method with care when high performance is required it is not yet tested with large data sets
+ ///
+ /// The value to convert
+ /// The target type to convert to
+ ///
+ /// The converted type
+ /// When is null and is value type and not nullable.
+ /// When an error occurs during conversion.
+ public static object ToType(this object value, Type type, CultureInfo culture)
+ {
+ if (value == null)
{
- if (value == null)
- {
- ThrowIfValueType();
+ ThrowIfValueType(type);
- return default;
- }
-
- return (T) value.ToType(typeof(T), DefaultCulture);
+ return null;
}
- ///
- /// Converts an object to another type.
- ///
- ///
- /// Also works with nullable types and enums. The method can't do this.
- /// This method can also be used to downcast numeric values for example from string (double) value "12,0" to short 12
- /// When trying to convert a string to double and the dutch culture is set, then this method tries to
- /// parse the string with custom logic. Because it occures that some string are not properly
- /// changed according to the current culture. For instance in dbf files where numeric values are stored as
- /// strings (for example "10,23")
- /// Use this method with care when high performance is required it is not yet tested with large data sets
- ///
- /// The value to convert
- /// The target type to convert to
- ///
- /// The converted type
- /// When is null and is value type and not nullable.
- /// When an error occurs during conversion.
- public static object ToType(this object value, Type type, CultureInfo culture)
+ if (type.IsEnum)
{
- if (value == null)
- {
- ThrowIfValueType(type);
+ return value.ToEnumType(type);
+ }
- return null;
- }
+ object result = null;
- if (type.IsEnum)
+ if (IsNullable(type))
+ {
+ try
{
- return value.ToEnumType(type);
+ var nullableConverter = new NullableConverter(type);
+ type = nullableConverter.UnderlyingType;
+ result = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
-
- object result = null;
-
- if (IsNullable(type))
+ catch
{
- try
- {
- var nullableConverter = new NullableConverter(type);
- type = nullableConverter.UnderlyingType;
- result = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
- }
- catch
- {
- result = null;
- }
+ result = null;
}
- else
+ }
+ else
+ {
+ try
{
- try
+ if (type == typeof(double) && value is string)
{
- if (type == typeof(double) && value is string)
+ if (Equals(culture, new CultureInfo("nl-NL")))
{
- if (Equals(culture, new CultureInfo("nl-NL")))
- {
- // TODO: Needs to be tested !!
- // TODO: replace parsing with regular expression
- // TODO: to make this more flexible make parser injectable through lambda's
+ // TODO: Needs to be tested !!
+ // TODO: replace parsing with regular expression
+ // TODO: to make this more flexible make parser injectable through lambda's
- var tmp = value as string;
- if (tmp.Contains(",") && !tmp.Contains(".")) // 1,5 -> 1.5
- {
- value = tmp.Replace(",", ".");
- }
- else if (tmp.Contains(",") && tmp.Contains(".") && tmp.Length > 4 && !tmp.Contains(" "))
- {
- // 100,000.00 -> 100000.00
- value = tmp.Replace(",", "");
- }
-
- //TODO: how to handle 100,000 english notation? Seems not to occur in most/mabye all situations
+ var tmp = value as string;
+ if (tmp.Contains(",") && !tmp.Contains(".")) // 1,5 -> 1.5
+ {
+ value = tmp.Replace(",", ".");
}
-
- result = value.Equals("NaN") ? Double.NaN : Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
- }
- else
- {
- // value needs to be downcasted
-
- switch (type.Name)
+ else if (tmp.Contains(",") && tmp.Contains(".") && tmp.Length > 4 && !tmp.Contains(" "))
{
- case "SByte":
- case "Byte":
- case "Int16":
- case "UInt16":
- case "Int32":
- case "UInt32":
- case "Int64":
- case "UInt64":
- object tmp = Convert.ChangeType(value, typeof(double), CultureInfo.InvariantCulture);
- result = Convert.ChangeType(tmp, type);
- break;
- default:
- result = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
- break;
+ // 100,000.00 -> 100000.00
+ value = tmp.Replace(",", "");
}
+
+ //TODO: how to handle 100,000 english notation? Seems not to occur in most/mabye all situations
}
+
+ result = value.Equals("NaN") ? Double.NaN : Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
- catch (Exception e)
+ else
{
- ThrowConversionException(value, type, e);
+ // value needs to be downcasted
+
+ switch (type.Name)
+ {
+ case "SByte":
+ case "Byte":
+ case "Int16":
+ case "UInt16":
+ case "Int32":
+ case "UInt32":
+ case "Int64":
+ case "UInt64":
+ object tmp = Convert.ChangeType(value, typeof(double), CultureInfo.InvariantCulture);
+ result = Convert.ChangeType(tmp, type);
+ break;
+ default:
+ result = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
+ break;
+ }
}
}
+ catch (Exception e)
+ {
+ ThrowConversionException(value, type, e);
+ }
+ }
- return result;
+ return result;
+ }
+
+ ///
+ /// Convert the value to the enum type
+ ///
+ /// The value to convert.
+ /// The type to convert to.
+ /// Ignores the case if set to true
+ /// The enum
+ public static object ToEnumType(this object value, Type type, bool ignoreCase = false)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
}
- ///
- /// Convert the value to the enum type
- ///
- /// The value to convert.
- /// The type to convert to.
- /// Ignores the case if set to true
- /// The enum
- public static object ToEnumType(this object value, Type type, bool ignoreCase = false)
+ if (!ignoreCase && !Enum.IsDefined(type, value))
{
- if (value == null)
- {
- throw new ArgumentNullException("value");
- }
+ ThrowConversionException(value, type, null);
+ }
- if (!ignoreCase && !Enum.IsDefined(type, value))
- {
- ThrowConversionException(value, type, null);
- }
+ var stringVal = value.ToString();
+ object result = null;
+ try
+ {
+ result = Enum.Parse(type, stringVal, ignoreCase);
+ }
+ catch (Exception e)
+ {
+ ThrowConversionException(value, type, e);
+ }
- var stringVal = value.ToString();
- object result = null;
- try
- {
- result = Enum.Parse(type, stringVal, ignoreCase);
- }
- catch (Exception e)
- {
- ThrowConversionException(value, type, e);
- }
+ return result;
+ }
- return result;
+ ///
+ /// Convert the value to the enum type
+ ///
+ /// The enum type to convert to
+ /// The value to convert.
+ /// A translation dictionary to handle items that do not match a given string representation
+ /// The enum
+ public static T ToEnumType(this object value, IDictionary lookup)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
}
- ///
- /// Convert the value to the enum type
- ///
- /// The enum type to convert to
- /// The value to convert.
- /// A translation dictionary to handle items that do not match a given string representation
- /// The enum
- public static T ToEnumType(this object value, IDictionary lookup)
+ var stringVal = value.ToString();
+ if (lookup != null && lookup.ContainsKey(stringVal))
{
- if (value == null)
+ return lookup[stringVal];
+ }
+
+ return (T) ToEnumType(value, typeof(T));
+ }
+
+ ///
+ /// Clone properties from an original object to a destination object.
+ ///
+ ///
+ /// Copy matching properties from object to object
+ /// http://goneale.wordpress.com/2009/02/16/cloning-object-properties-via-reflection/#
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void CloneProperties(this T1 origin, T2 destination, params string[] excludedProperties)
+ {
+ // Instantiate if necessary
+ if (destination == null)
+ {
+ throw new ArgumentNullException("destination", "Destination object must first be instantiated.");
+ }
+
+ // Loop through each property in the destination
+ foreach (PropertyInfo destinationProperty in destination.GetType().GetProperties())
+ {
+ var excluded = false;
+ foreach (string excludedProperty in excludedProperties)
{
- throw new ArgumentNullException("value");
+ if (excludedProperty.ToLower().Equals(destinationProperty.Name.ToLower()))
+ {
+ excluded = true;
+ }
}
- var stringVal = value.ToString();
- if (lookup != null && lookup.ContainsKey(stringVal))
+ if (excluded || IsIList(destinationProperty) || IsIDictionary(destinationProperty)
+ || IsGenericIList(destinationProperty) || IsGenericIDictionary(destinationProperty))
{
- return lookup[stringVal];
+ continue;
}
- return (T) ToEnumType(value, typeof(T));
+ // find and set val if we can find a matching property name and matching type in the origin with the origin's value
+ if (!origin.Equals(default(T1)) && destinationProperty.CanWrite)
+ {
+ PropertyInfo propertyInfo = destinationProperty;
+ origin.GetType().GetProperties().Where(
+ x => x.CanRead && (x.Name == propertyInfo.Name && x.PropertyType == propertyInfo.PropertyType))
+ .ToList()
+ .ForEach(x => propertyInfo.SetValue(destination, x.GetValue(origin, null), null));
+ }
}
+ }
- ///
- /// Clone properties from an original object to a destination object.
- ///
- ///
- /// Copy matching properties from object to object
- /// http://goneale.wordpress.com/2009/02/16/cloning-object-properties-via-reflection/#
- ///
- ///
- ///
- ///
- ///
- ///
- public static void CloneProperties(this T1 origin, T2 destination, params string[] excludedProperties)
+ ///
+ /// Sets the object value.
+ ///
+ ///
+ /// The property info.
+ /// The destination object
+ /// The value
+ /// The translator
+ public static void SetObjectValue(this PropertyInfo pInfo, T dest, object value,
+ Func