Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.Entity / System / Data / SqlClient / SqlTypesAssembly.cs
blobc9213bb2555f4503a357a1136fe5b9cb39bf990d
1 //------------------------------------------------------------------------------
2 // <copyright file="SqlTypesAssembly.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //
6 // @owner willa
7 // @backupOwner Microsoft
8 //------------------------------------------------------------------------------
10 using System.Collections.Generic;
11 using System.Data.Common.Utils;
12 using System.Data.Spatial;
13 using System.Data.SqlClient.Internal;
14 using System.Diagnostics;
15 using System.IO;
16 using System.Linq.Expressions;
17 using System.Reflection;
19 namespace System.Data.SqlClient
21 internal static class Expressions
23 internal static Expression Null<TNullType>()
25 return Expression.Constant(null, typeof(TNullType));
28 internal static Expression Null(Type nullType)
30 return Expression.Constant(null, nullType);
33 internal static Expression<Func<TArg, TResult>> Lambda<TArg, TResult>(string argumentName, Func<ParameterExpression, Expression> createLambdaBodyGivenParameter)
35 ParameterExpression argParam = Expression.Parameter(typeof(TArg), argumentName);
36 Expression lambdaBody = createLambdaBodyGivenParameter(argParam);
37 return Expression.Lambda<Func<TArg, TResult>>(lambdaBody, argParam);
40 internal static Expression Call(this Expression exp, string methodName)
42 return Expression.Call(exp, methodName, Type.EmptyTypes);
45 internal static Expression ConvertTo(this Expression exp, Type convertToType)
47 return Expression.Convert(exp, convertToType);
50 internal static Expression ConvertTo<TConvertToType>(this Expression exp)
52 return Expression.Convert(exp, typeof(TConvertToType));
55 internal sealed class ConditionalExpressionBuilder
57 private readonly Expression condition;
58 private readonly Expression ifTrueThen;
60 internal ConditionalExpressionBuilder(Expression conditionExpression, Expression ifTrueExpression)
62 this.condition = conditionExpression;
63 this.ifTrueThen = ifTrueExpression;
66 internal Expression Else(Expression resultIfFalse)
68 return Expression.Condition(this.condition, ifTrueThen, resultIfFalse);
72 internal static ConditionalExpressionBuilder IfTrueThen(this Expression conditionExp, Expression resultIfTrue)
74 return new ConditionalExpressionBuilder(conditionExp, resultIfTrue);
77 internal static Expression Property<TPropertyType>(this Expression exp, string propertyName)
79 PropertyInfo prop = exp.Type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
80 Debug.Assert(prop != null, "Type '" + exp.Type.FullName + "' does not declare a public instance property with the name '" + propertyName + "'");
82 return Expression.Property(exp, prop);
86 /// <summary>
87 /// SqlTypesAssembly allows for late binding to the capabilities of a specific version of the Microsoft.SqlServer.Types assembly
88 /// </summary>
89 internal sealed class SqlTypesAssembly
91 private static readonly System.Collections.ObjectModel.ReadOnlyCollection<string> preferredSqlTypesAssemblies = new List<string>()
93 "Microsoft.SqlServer.Types, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91",
94 "Microsoft.SqlServer.Types, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91",
95 }.AsReadOnly();
97 private static SqlTypesAssembly BindToLatest()
99 Assembly sqlTypesAssembly = null;
100 foreach (string assemblyFullName in preferredSqlTypesAssemblies)
102 AssemblyName asmName = new AssemblyName(assemblyFullName);
105 sqlTypesAssembly = Assembly.Load(asmName);
106 break;
108 catch (FileNotFoundException)
111 catch (FileLoadException)
116 if (sqlTypesAssembly != null)
118 return new SqlTypesAssembly(sqlTypesAssembly);
120 return null;
123 internal static bool TryGetSqlTypesAssembly(Assembly assembly, out SqlTypesAssembly sqlAssembly)
125 if (IsKnownAssembly(assembly))
127 sqlAssembly = new SqlTypesAssembly(assembly);
128 return true;
130 sqlAssembly = null;
131 return false;
134 private static bool IsKnownAssembly(Assembly assembly)
136 foreach (string knownAssemblyFullName in preferredSqlTypesAssemblies)
138 if (EntityUtil.AssemblyNamesMatch(assembly.FullName, new AssemblyName(knownAssemblyFullName)))
140 return true;
143 return false;
146 private static Singleton<SqlTypesAssembly> latestVersion = new Singleton<SqlTypesAssembly>(BindToLatest);
148 /// <summary>
149 /// Returns the highest available version of the Microsoft.SqlServer.Types assembly that could be located using Assembly.Load; may return <c>null</c> if no version of the assembly could be found.
150 /// </summary>
151 internal static SqlTypesAssembly Latest { get { return latestVersion.Value; } }
153 private SqlTypesAssembly(Assembly sqlSpatialAssembly)
155 // Retrieve SQL Server spatial types and static constructor methods
156 Type sqlGeog = sqlSpatialAssembly.GetType("Microsoft.SqlServer.Types.SqlGeography", throwOnError: true);
157 Type sqlGeom = sqlSpatialAssembly.GetType("Microsoft.SqlServer.Types.SqlGeometry", throwOnError: true);
159 Debug.Assert(sqlGeog != null, "SqlGeography type was not properly retrieved?");
160 Debug.Assert(sqlGeom != null, "SqlGeometry type was not properly retrieved?");
162 this.SqlGeographyType = sqlGeog;
163 this.sqlGeographyFromWKTString = CreateStaticConstructorDelegate<string>(sqlGeog, "STGeomFromText");
164 this.sqlGeographyFromWKBByteArray = CreateStaticConstructorDelegate<byte[]>(sqlGeog, "STGeomFromWKB");
165 this.sqlGeographyFromGMLReader = CreateStaticConstructorDelegate<System.Xml.XmlReader>(sqlGeog, "GeomFromGml");
167 this.SqlGeometryType = sqlGeom;
168 this.sqlGeometryFromWKTString = CreateStaticConstructorDelegate<string>(sqlGeom, "STGeomFromText");
169 this.sqlGeometryFromWKBByteArray = CreateStaticConstructorDelegate<byte[]>(sqlGeom, "STGeomFromWKB");
170 this.sqlGeometryFromGMLReader = CreateStaticConstructorDelegate<System.Xml.XmlReader>(sqlGeom, "GeomFromGml");
172 // Retrieve SQL Server specific primitive types
173 MethodInfo asTextMethod = this.SqlGeometryType.GetMethod("STAsText", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
174 this.SqlCharsType = asTextMethod.ReturnType;
175 this.SqlStringType = this.SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlString", throwOnError: true);
176 this.SqlBooleanType = this.SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlBoolean", throwOnError: true);
177 this.SqlBytesType = this.SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlBytes", throwOnError: true);
178 this.SqlDoubleType = this.SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlDouble", throwOnError: true);
179 this.SqlInt32Type = this.SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlInt32", throwOnError: true);
180 this.SqlXmlType = this.SqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlXml", throwOnError: true);
182 // Create type conversion delegates to SQL Server types
183 this.sqlBytesFromByteArray = Expressions.Lambda<byte[], object>("binaryValue", bytesVal => BuildConvertToSqlBytes(bytesVal, this.SqlBytesType)).Compile();
184 this.sqlStringFromString = Expressions.Lambda<string, object>("stringValue", stringVal => BuildConvertToSqlString(stringVal, this.SqlStringType)).Compile();
185 this.sqlCharsFromString = Expressions.Lambda<string, object>("stringValue", stringVal => BuildConvertToSqlChars(stringVal, this.SqlCharsType)).Compile();
186 this.sqlXmlFromXmlReader = Expressions.Lambda<System.Xml.XmlReader, object>("readerVaue", readerVal => BuildConvertToSqlXml(readerVal, this.SqlXmlType)).Compile();
188 // Create type conversion delegates from SQL Server types; all arguments are typed as 'object' and require Expression.Convert before use of members of the SQL Server type.
190 // Explicit cast from SqlBoolean to bool
191 this.sqlBooleanToBoolean = Expressions.Lambda<object, bool>("sqlBooleanValue", sqlBoolVal => sqlBoolVal.ConvertTo(this.SqlBooleanType).ConvertTo<bool>()).Compile();
193 // Explicit cast from SqlBoolean to bool? for non-Null values; otherwise null
194 this.sqlBooleanToNullableBoolean = Expressions.Lambda<object, bool?>("sqlBooleanValue", sqlBoolVal =>
195 sqlBoolVal.ConvertTo(this.SqlBooleanType).Property<bool>("IsNull")
196 .IfTrueThen(Expressions.Null<bool?>())
197 .Else(sqlBoolVal.ConvertTo(this.SqlBooleanType).ConvertTo<bool>().ConvertTo<bool?>())).Compile();
199 // SqlBytes has instance byte[] property 'Value'
200 this.sqlBytesToByteArray = Expressions.Lambda<object, byte[]>("sqlBytesValue", sqlBytesVal => sqlBytesVal.ConvertTo(this.SqlBytesType).Property<byte[]>("Value")).Compile();
202 // SqlChars -> SqlString, SqlString has instance string property 'Value'
203 this.sqlCharsToString = Expressions.Lambda<object, string>("sqlCharsValue", sqlCharsVal => sqlCharsVal.ConvertTo(this.SqlCharsType).Call("ToSqlString").Property<string>("Value")).Compile();
205 // Explicit cast from SqlString to string
206 this.sqlStringToString = Expressions.Lambda<object, string>("sqlStringValue", sqlStringVal => sqlStringVal.ConvertTo(this.SqlStringType).Property<string>("Value")).Compile();
208 // Explicit cast from SqlDouble to double
209 this.sqlDoubleToDouble = Expressions.Lambda<object, double>("sqlDoubleValue", sqlDoubleVal => sqlDoubleVal.ConvertTo(this.SqlDoubleType).ConvertTo<double>()).Compile();
211 // Explicit cast from SqlDouble to double? for non-Null values; otherwise null
212 this.sqlDoubleToNullableDouble = Expressions.Lambda<object, double?>("sqlDoubleValue", sqlDoubleVal =>
213 sqlDoubleVal.ConvertTo(this.SqlDoubleType).Property<bool>("IsNull")
214 .IfTrueThen(Expressions.Null<double?>())
215 .Else(sqlDoubleVal.ConvertTo(this.SqlDoubleType).ConvertTo<double>().ConvertTo<double?>())).Compile();
217 // Explicit cast from SqlInt32 to int
218 this.sqlInt32ToInt = Expressions.Lambda<object, int>("sqlInt32Value", sqlInt32Val => sqlInt32Val.ConvertTo(this.SqlInt32Type).ConvertTo<int>()).Compile();
220 // Explicit cast from SqlInt32 to int? for non-Null values; otherwise null
221 this.sqlInt32ToNullableInt = Expressions.Lambda<object, int?>("sqlInt32Value", sqlInt32Val =>
222 sqlInt32Val.ConvertTo(this.SqlInt32Type).Property<bool>("IsNull")
223 .IfTrueThen(Expressions.Null<int?>())
224 .Else(sqlInt32Val.ConvertTo(this.SqlInt32Type).ConvertTo<int>().ConvertTo<int?>())).Compile();
226 // SqlXml has instance string property 'Value'
227 this.sqlXmlToString = Expressions.Lambda<object, string>("sqlXmlValue", sqlXmlVal => sqlXmlVal.ConvertTo(this.SqlXmlType).Property<string>("Value")).Compile();
229 this.isSqlGeographyNull = Expressions.Lambda<object, bool>("sqlGeographyValue", sqlGeographyValue => sqlGeographyValue.ConvertTo(this.SqlGeographyType).Property<bool>("IsNull")).Compile();
230 this.isSqlGeometryNull = Expressions.Lambda<object, bool>("sqlGeometryValue", sqlGeometryValue => sqlGeometryValue.ConvertTo(this.SqlGeometryType).Property<bool>("IsNull")).Compile();
232 this.geographyAsTextZMAsSqlChars = Expressions.Lambda<object, object>("sqlGeographyValue", sqlGeographyValue => sqlGeographyValue.ConvertTo(this.SqlGeographyType).Call("AsTextZM")).Compile();
233 this.geometryAsTextZMAsSqlChars = Expressions.Lambda<object, object>("sqlGeometryValue", sqlGeometryValue => sqlGeometryValue.ConvertTo(this.SqlGeometryType).Call("AsTextZM")).Compile();
236 #region 'Public' API
238 #region Primitive Types and Type Conversions
240 internal Type SqlBooleanType { get; private set; }
241 internal Type SqlBytesType { get; private set; }
242 internal Type SqlCharsType { get; private set; }
243 internal Type SqlStringType { get; private set; }
244 internal Type SqlDoubleType { get; private set; }
245 internal Type SqlInt32Type { get; private set; }
246 internal Type SqlXmlType { get; private set; }
248 private readonly Func<object, bool> sqlBooleanToBoolean;
249 internal bool SqlBooleanToBoolean(object sqlBooleanValue)
251 return this.sqlBooleanToBoolean(sqlBooleanValue);
254 private readonly Func<object, bool?> sqlBooleanToNullableBoolean;
255 internal bool? SqlBooleanToNullableBoolean(object sqlBooleanValue)
257 if (sqlBooleanToBoolean == null)
259 return null;
262 return this.sqlBooleanToNullableBoolean(sqlBooleanValue);
265 private readonly Func<byte[], object> sqlBytesFromByteArray;
266 internal object SqlBytesFromByteArray(byte[] binaryValue)
268 return sqlBytesFromByteArray(binaryValue);
271 private readonly Func<object, byte[]> sqlBytesToByteArray;
272 internal byte[] SqlBytesToByteArray(object sqlBytesValue)
274 if (sqlBytesValue == null)
276 return null;
279 return this.sqlBytesToByteArray(sqlBytesValue);
282 private readonly Func<string, object> sqlStringFromString;
283 internal object SqlStringFromString(string stringValue)
285 return sqlStringFromString(stringValue);
288 private readonly Func<string, object> sqlCharsFromString;
289 internal object SqlCharsFromString(string stringValue)
291 return sqlCharsFromString(stringValue);
294 private readonly Func<object, string> sqlCharsToString;
295 internal string SqlCharsToString(object sqlCharsValue)
297 if (sqlCharsValue == null)
299 return null;
301 return this.sqlCharsToString(sqlCharsValue);
304 private readonly Func<object, string> sqlStringToString;
305 internal string SqlStringToString(object sqlStringValue)
307 if (sqlStringValue == null)
309 return null;
311 return this.sqlStringToString(sqlStringValue);
314 private readonly Func<object, double> sqlDoubleToDouble;
315 internal double SqlDoubleToDouble(object sqlDoubleValue)
317 return this.sqlDoubleToDouble(sqlDoubleValue);
320 private readonly Func<object, double?> sqlDoubleToNullableDouble;
321 internal double? SqlDoubleToNullableDouble(object sqlDoubleValue)
323 if (sqlDoubleValue == null)
325 return null;
327 return this.sqlDoubleToNullableDouble(sqlDoubleValue);
330 private readonly Func<object, int> sqlInt32ToInt;
331 internal int SqlInt32ToInt(object sqlInt32Value)
333 return this.sqlInt32ToInt(sqlInt32Value);
336 private readonly Func<object, int?> sqlInt32ToNullableInt;
337 internal int? SqlInt32ToNullableInt(object sqlInt32Value)
339 if (sqlInt32Value == null)
341 return null;
343 return this.sqlInt32ToNullableInt(sqlInt32Value);
346 private readonly Func<System.Xml.XmlReader, object> sqlXmlFromXmlReader;
347 internal object SqlXmlFromString(string stringValue)
349 System.Xml.XmlReader xmlReader = XmlReaderFromString(stringValue);
350 return sqlXmlFromXmlReader(xmlReader);
353 private readonly Func<object, string> sqlXmlToString;
354 internal string SqlXmlToString(object sqlXmlValue)
356 if (sqlXmlValue == null)
358 return null;
361 return sqlXmlToString(sqlXmlValue);
364 private readonly Func<object, bool> isSqlGeographyNull;
365 internal bool IsSqlGeographyNull(object sqlGeographyValue)
367 if (sqlGeographyValue == null)
369 return true;
372 return isSqlGeographyNull(sqlGeographyValue);
375 private readonly Func<object, bool> isSqlGeometryNull;
376 internal bool IsSqlGeometryNull(object sqlGeometryValue)
378 if (sqlGeometryValue == null)
380 return true;
383 return isSqlGeometryNull(sqlGeometryValue);
386 private readonly Func<object, object> geographyAsTextZMAsSqlChars;
387 internal string GeographyAsTextZM(DbGeography geographyValue)
389 if (geographyValue == null)
391 return null;
394 object sqlGeographyValue = ConvertToSqlTypesGeography(geographyValue);
395 object chars = this.geographyAsTextZMAsSqlChars(sqlGeographyValue);
396 return this.SqlCharsToString(chars);
399 private readonly Func<object, object> geometryAsTextZMAsSqlChars;
400 internal string GeometryAsTextZM(DbGeometry geometryValue)
402 if (geometryValue == null)
404 return null;
407 object sqlGeometryValue = ConvertToSqlTypesGeometry(geometryValue);
408 object chars = this.geometryAsTextZMAsSqlChars(sqlGeometryValue);
409 return this.SqlCharsToString(chars);
411 #endregion
413 #region Spatial Types and Spatial Factory Methods
415 internal Type SqlGeographyType { get; private set; }
416 internal Type SqlGeometryType { get; private set; }
418 internal object ConvertToSqlTypesGeography(DbGeography geographyValue)
420 geographyValue.CheckNull("geographyValue");
421 object result = GetSqlTypesSpatialValue(geographyValue.AsSpatialValue(), SqlGeographyType);
422 return result;
425 internal object SqlTypesGeographyFromBinary(byte[] wellKnownBinary, int srid)
427 Debug.Assert(wellKnownBinary != null, "Validate WKB before calling SqlTypesGeographyFromBinary");
428 return sqlGeographyFromWKBByteArray(wellKnownBinary, srid);
431 internal object SqlTypesGeographyFromText(string wellKnownText, int srid)
433 Debug.Assert(wellKnownText != null, "Validate WKT before calling SqlTypesGeographyFromText");
434 return sqlGeographyFromWKTString(wellKnownText, srid);
437 internal object ConvertToSqlTypesGeometry(DbGeometry geometryValue)
439 geometryValue.CheckNull("geometryValue");
440 object result = GetSqlTypesSpatialValue(geometryValue.AsSpatialValue(), SqlGeometryType);
441 return result;
444 internal object SqlTypesGeometryFromBinary(byte[] wellKnownBinary, int srid)
446 Debug.Assert(wellKnownBinary != null, "Validate WKB before calling SqlTypesGeometryFromBinary");
447 return sqlGeometryFromWKBByteArray(wellKnownBinary, srid);
450 internal object SqlTypesGeometryFromText(string wellKnownText, int srid)
452 Debug.Assert(wellKnownText != null, "Validate WKT before calling SqlTypesGeometryFromText");
453 return sqlGeometryFromWKTString(wellKnownText, srid);
456 #endregion
458 #endregion
460 private object GetSqlTypesSpatialValue(IDbSpatialValue spatialValue, Type requiredProviderValueType)
462 Debug.Assert(spatialValue != null, "Ensure spatial value is non-null before calling GetSqlTypesSpatialValue");
464 // If the specified value was created by this spatial services implementation, its underlying Microsoft.SqlServer.Types.SqlGeography value is available via the ProviderValue property.
465 object providerValue = spatialValue.ProviderValue;
466 if (providerValue != null && providerValue.GetType() == requiredProviderValueType)
468 return providerValue;
471 // Otherwise, attempt to retrieve a Well Known Binary, Well Known Text or GML (in descending order of preference) representation of the value that can be used to create an appropriate Microsoft.SqlServer.Types.SqlGeography/SqlGeometry value
473 int? srid = spatialValue.CoordinateSystemId;
474 if (srid.HasValue)
476 // Well Known Binary (WKB)
477 byte[] binaryValue = spatialValue.WellKnownBinary;
478 if (binaryValue != null)
480 return (spatialValue.IsGeography ? sqlGeographyFromWKBByteArray(binaryValue, srid.Value) : sqlGeometryFromWKBByteArray(binaryValue, srid.Value));
483 // Well Known Text (WKT)
484 string textValue = spatialValue.WellKnownText;
485 if (textValue != null)
487 return (spatialValue.IsGeography ? sqlGeographyFromWKTString(textValue, srid.Value) : sqlGeometryFromWKTString(textValue, srid.Value));
490 // Geography Markup Language (GML), as a string
491 string gmlValue = spatialValue.GmlString;
492 if (gmlValue != null)
494 var xmlReader = XmlReaderFromString(gmlValue);
495 return (spatialValue.IsGeography ? sqlGeographyFromGMLReader(xmlReader, srid.Value) : sqlGeometryFromGMLReader(xmlReader, srid.Value));
499 throw spatialValue.NotSqlCompatible();
502 private static System.Xml.XmlReader XmlReaderFromString(string stringValue)
504 return System.Xml.XmlReader.Create(new System.IO.StringReader(stringValue));
507 private readonly Func<string, int, object> sqlGeographyFromWKTString;
508 private readonly Func<byte[], int, object> sqlGeographyFromWKBByteArray;
509 private readonly Func<System.Xml.XmlReader, int, object> sqlGeographyFromGMLReader;
511 private readonly Func<string, int, object> sqlGeometryFromWKTString;
512 private readonly Func<byte[], int, object> sqlGeometryFromWKBByteArray;
513 private readonly Func<System.Xml.XmlReader, int, object> sqlGeometryFromGMLReader;
515 #region Expression Compilation Helpers
517 private static Func<TArg, int, object> CreateStaticConstructorDelegate<TArg>(Type spatialType, string methodName)
519 Debug.Assert(spatialType != null, "Ensure spatialType is non-null before calling CreateStaticConstructorDelegate");
520 var dataParam = Expression.Parameter(typeof(TArg));
521 var sridParam = Expression.Parameter(typeof(int));
522 var staticCtorMethod = spatialType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);
523 Debug.Assert(staticCtorMethod != null, "Could not find method '" + methodName + "' on type '" + spatialType.FullName + "'");
524 Debug.Assert(staticCtorMethod.GetParameters().Length == 2 && staticCtorMethod.GetParameters()[1].ParameterType == typeof(int), "Static constructor method on '" + spatialType.FullName + "' does not match static constructor pattern?");
526 Expression sqlData = BuildConvertToSqlType(dataParam, staticCtorMethod.GetParameters()[0].ParameterType);
528 var ex = Expression.Lambda<Func<TArg, int, object>>(Expression.Call(null, staticCtorMethod, sqlData, sridParam), dataParam, sridParam);
529 var result = ex.Compile();
530 return result;
533 private static Expression BuildConvertToSqlType(Expression toConvert, Type convertTo)
535 if (toConvert.Type == typeof(byte[]))
537 return BuildConvertToSqlBytes(toConvert, convertTo);
539 else if (toConvert.Type == typeof(string))
541 if (convertTo.Name == "SqlString")
543 return BuildConvertToSqlString(toConvert, convertTo);
545 else
547 return BuildConvertToSqlChars(toConvert, convertTo);
550 else
552 Debug.Assert(toConvert.Type == typeof(System.Xml.XmlReader), "Argument to static constructor method was not byte[], string or XmlReader?");
553 if (toConvert.Type == typeof(System.Xml.XmlReader))
555 return BuildConvertToSqlXml(toConvert, convertTo);
559 return toConvert;
562 private static Expression BuildConvertToSqlBytes(Expression toConvert, Type sqlBytesType)
564 // dataParam:byte[] => new SqlBytes(dataParam)
565 Debug.Assert(sqlBytesType.Name == "SqlBytes", "byte[] argument used with non-SqlBytes static constructor method?");
566 ConstructorInfo byteArrayCtor = sqlBytesType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[] { toConvert.Type }, null);
567 Debug.Assert(byteArrayCtor != null, "SqlXml(System.IO.Stream) constructor not found?");
568 Expression result = Expression.New(byteArrayCtor, toConvert);
569 return result;
572 private static Expression BuildConvertToSqlChars(Expression toConvert, Type sqlCharsType)
574 // dataParam:String => new SqlChars(new SqlString(dataParam))
575 Debug.Assert(sqlCharsType.Name == "SqlChars", "String argument used with non-SqlChars static constructor method?");
576 Type sqlString = sqlCharsType.Assembly.GetType("System.Data.SqlTypes.SqlString", throwOnError: true);
577 ConstructorInfo sqlCharsFromSqlStringCtor = sqlCharsType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[] { sqlString }, null);
578 Debug.Assert(sqlCharsFromSqlStringCtor != null, "SqlXml(System.IO.Stream) constructor not found?");
579 ConstructorInfo sqlStringFromStringCtor = sqlString.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
580 Expression result = Expression.New(sqlCharsFromSqlStringCtor, Expression.New(sqlStringFromStringCtor, toConvert));
581 return result;
584 private static Expression BuildConvertToSqlString(Expression toConvert, Type sqlStringType)
586 // dataParam:String => new SqlString(dataParam)
587 Debug.Assert(sqlStringType.Name == "SqlString", "String argument used with non-SqlString static constructor method?");
588 ConstructorInfo sqlStringFromStringCtor = sqlStringType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
589 Debug.Assert(sqlStringFromStringCtor != null);
590 Expression result = Expression.Convert(Expression.New(sqlStringFromStringCtor, toConvert), typeof(object));
591 return result;
594 private static Expression BuildConvertToSqlXml(Expression toConvert, Type sqlXmlType)
596 // dataParam:Stream => new SqlXml(dataParam)
597 Debug.Assert(sqlXmlType.Name == "SqlXml", "Stream argument used with non-SqlXml static constructor method?");
598 ConstructorInfo readerCtor = sqlXmlType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[] { toConvert.Type }, null);
599 Debug.Assert(readerCtor != null, "SqlXml(System.Xml.XmlReader) constructor not found?");
600 Expression result = Expression.New(readerCtor, toConvert);
601 return result;
604 #endregion