internal static object CoerceValue(object value, MetaType destinationType, out bool coercedToDataFeed, out bool typeChanged, bool allowStreaming = true)
{
Debug.Assert(!(value is DataFeed), "Value provided should not already be a data feed");
Debug.Assert(!ADP.IsNull(value), "Value provided should not be null");
Debug.Assert(null != destinationType, "null destinationType");
coercedToDataFeed = false;
typeChanged = false;
Type currentType = value.GetType();
if ((typeof(object) != destinationType.ClassType) &&
(currentType != destinationType.ClassType) &&
((currentType != destinationType.SqlType) || (SqlDbType.Xml == destinationType.SqlDbType)))
{ // Special case for Xml types (since we need to convert SqlXml into a string)
try
{
// Assume that the type changed
typeChanged = true;
if ((typeof(string) == destinationType.ClassType))
{
// For Xml data, destination Type is always string
if (typeof(SqlXml) == currentType)
{
value = MetaType.GetStringFromXml((XmlReader)(((SqlXml)value).CreateReader()));
}
else if (typeof(SqlString) == currentType)
{
typeChanged = false; // Do nothing
}
else if (typeof(XmlReader).IsAssignableFrom(currentType))
{
if (allowStreaming)
{
coercedToDataFeed = true;
value = new XmlDataFeed((XmlReader)value);
}
else
{
value = MetaType.GetStringFromXml((XmlReader)value);
}
}
else if (typeof(char[]) == currentType)
{
value = new string((char[])value);
}
else if (typeof(SqlChars) == currentType)
{
value = new string(((SqlChars)value).Value);
}
else if (value is TextReader && allowStreaming)
{
coercedToDataFeed = true;
value = new TextDataFeed((TextReader)value);
}
else
{
value = Convert.ChangeType(value, destinationType.ClassType, (IFormatProvider)null);
}
}
else if ((DbType.Currency == destinationType.DbType) && (typeof(string) == currentType))
{
value = Decimal.Parse((string)value, NumberStyles.Currency, (IFormatProvider)null); // WebData 99376
}
else if ((typeof(SqlBytes) == currentType) && (typeof(byte[]) == destinationType.ClassType))
{
typeChanged = false; // Do nothing
}
else if ((typeof(string) == currentType) && (SqlDbType.Time == destinationType.SqlDbType))
{
value = TimeSpan.Parse((string)value);
}
else if ((typeof(string) == currentType) && (SqlDbType.DateTimeOffset == destinationType.SqlDbType))
{
value = DateTimeOffset.Parse((string)value, (IFormatProvider)null);
}
else if ((typeof(DateTime) == currentType) && (SqlDbType.DateTimeOffset == destinationType.SqlDbType))
{
value = new DateTimeOffset((DateTime)value);
}
else if (TdsEnums.SQLTABLE == destinationType.TDSType && (
value is DbDataReader ||
value is System.Collections.Generic.IEnumerable<SqlDataRecord>))
{
// no conversion for TVPs.
typeChanged = false;
}
else if (destinationType.ClassType == typeof(byte[]) && value is Stream && allowStreaming)
{
coercedToDataFeed = true;
value = new StreamDataFeed((Stream)value);
}
else
{
value = Convert.ChangeType(value, destinationType.ClassType, (IFormatProvider)null);
}
}
catch (Exception e)
{
if (!ADP.IsCatchableExceptionType(e))
{
throw;
}
throw ADP.ParameterConversionFailed(value, destinationType.ClassType, e); // WebData 75433
}
}
Debug.Assert(allowStreaming || !coercedToDataFeed, "Streaming is not allowed, but type was coerced into a data feed");
Debug.Assert(value.GetType() == currentType ^ typeChanged, "Incorrect value for typeChanged");
return value;
}