/// <summary> /// 返回从源类型到目标类型的用户定义的显式转换方法。 /// 该转换方法的参数与源类型和目标类型并不一定完全相同,但保证存在标准显式转换。 /// </summary> /// <param name="sourceType">要获取用户定义的转换方法的源类型。</param> /// <param name="targetType">要获取用户定义的转换方法的目标类型。</param> /// <returns>如果存在从源类型到目标类型的用户定义的显式转换方法,则返回该方法; /// 否则返回 <c>null</c>。</returns> public static ConversionMethod GetExplicitConversion(Type sourceType, Type targetType) { Type exactSource = null, exactTarget = null; UniqueValue<ConversionMethod> method = new UniqueValue<ConversionMethod>(); Conversion conv = GetTypeConversions(sourceType.GetNonNullableType()); for (int i = conv.ConvertToIndex; i < conv.Methods.Length; i++) { ConversionMethod m = conv.Methods[i]; if (targetType.IsStandardExplicitFrom(m.TargetType)) { GetBestConversion(m, ref exactSource, ref exactTarget, method); } } conv = GetTypeConversions(targetType.GetNonNullableType()); for (int i = Conversion.ConvertFromIndex; i < conv.ConvertToIndex; i++) { ConversionMethod m = conv.Methods[i]; if (m.SourceType.IsStandardExplicitFrom(sourceType)) { GetBestConversion(m, ref exactSource, ref exactTarget, method); } } if (method.IsUnique) { return method.Value; } return null; }
object ReadValue(XmlReader reader, Type type) { var notNullableType = type.GetNonNullableType(); if (notNullableType == typeof (DateTime) || notNullableType == typeof (DateTimeOffset)) { reader.Read(); DateTimeOffset value; if (DateTimeOffset.TryParseExact( reader.Value, Settings.DateTimeFormatString, Settings.Culture, DateTimeStyles.None, out value)) { return value; } if (notNullableType != type) return type.GetDefault(); throw new DeserializationException(reader.Value, type); } var typeCode = Type.GetTypeCode(type); if (typeCode == TypeCode.Object) { return Read(reader, type); } reader.Read(); return Convert.ChangeType(reader.Value, type); }
private static System.Web.Routing.RouteValueDictionary ValueBoxHtmlAttributes(this System.Type type) { System.Type _type = type.IsNullableType() ? type.GetNonNullableType() : type; return(new System.Web.Routing.RouteValueDictionary { { "datatype", _type.FullName.Replace('.', '_') } }); }
/// <summary> /// If the result of an isinst opcode is known statically, this /// returns the result, otherwise it returns null, meaning we'll need /// to perform the IsInst instruction at runtime. /// /// The result of this function must be equivalent to IsInst, or /// null. /// </summary> private static AnalyzeTypeIsResult AnalyzeTypeIs(Expression operand, Type testType) { Type operandType = operand.Type; // An expression is either of type void, or it isn't. if (operandType == typeof(void)) { return testType == typeof(void) ? AnalyzeTypeIsResult.KnownTrue : AnalyzeTypeIsResult.KnownFalse; } if (testType == typeof(void)) { return AnalyzeTypeIsResult.KnownFalse; } // // Type comparisons treat nullable types as if they were the // underlying type. The reason is when you box a nullable it // becomes a boxed value of the underlying type, or null. // Type nnOperandType = operandType.GetNonNullableType(); Type nnTestType = testType.GetNonNullableType(); // // See if we can determine the answer based on the static types // // Extensive testing showed that Type.IsAssignableFrom, // Type.IsInstanceOfType, and the isinst instruction were all // equivalent when used against a live object // if (nnTestType.IsAssignableFrom(nnOperandType)) { // If the operand is a value type (other than nullable), we // know the result is always true. if (operandType.GetTypeInfo().IsValueType && !operandType.IsNullableType()) { return AnalyzeTypeIsResult.KnownTrue; } // For reference/nullable types, we need to compare to null at runtime return AnalyzeTypeIsResult.KnownAssignable; } // We used to have an if IsSealed, return KnownFalse check here. // but that doesn't handle generic types & co/contravariance correctly. // So just use IsInst, which we know always gives us the right answer. // Otherwise we need a full runtime check return AnalyzeTypeIsResult.Unknown; }
private static AnalyzeTypeIsResult AnalyzeTypeIs(Expression operand, Type testType) { Type type = operand.Type; if (type == typeof(void)) { return AnalyzeTypeIsResult.KnownFalse; } Type nonNullableType = type.GetNonNullableType(); if (!testType.GetNonNullableType().IsAssignableFrom(nonNullableType)) { return AnalyzeTypeIsResult.Unknown; } if (type.IsValueType && !type.IsNullableType()) { return AnalyzeTypeIsResult.KnownTrue; } return AnalyzeTypeIsResult.KnownAssignable; }
internal static bool IsArithmetic(Type type) { type = type.GetNonNullableType(); if (!type.IsEnum) { switch (Type.GetTypeCode(type)) { case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: return true; } } return false; }
public static IQueryBuilder <T> GreaterThan <T, P>(this IQueryBuilder <T> q, Expression <Func <T, P> > property, P value) { Type type = typeof(P); var constantvalue = Expression.Constant(value); var propertyBody = GetMemberExpression(q, property); Expression nonNullProperty = propertyBody; //如果是Nullable<X>类型,则转化成X类型 if (type.IsNullableType()) { type = type.GetNonNullableType(); nonNullProperty = Expression.Convert(propertyBody, type); } var c = Expression.GreaterThan(nonNullProperty, constantvalue); q.AppendExpression(c); return(q); }
/// <summary> /// 建立 Between 查询条件 /// </summary> /// <typeparam name="T">实体</typeparam> /// <param name="q">动态查询条件创建者</param> /// <param name="property">属性</param> /// <param name="from">开始值</param> /// <param name="to">结束值</param> /// <returns></returns> public static IQueryBuilder <T> Between <T, P>(this IQueryBuilder <T> q, Expression <Func <T, P> > property, P from, P to) { Type type = typeof(P); var constantFrom = Expression.Constant(from); var constantTo = Expression.Constant(to); var propertyBody = GetMemberExpression(q, property); Expression nonNullProperty = propertyBody; //如果是Nullable<X>类型,则转化成X类型 if (type.IsNullableType()) { type = type.GetNonNullableType(); nonNullProperty = Expression.Convert(propertyBody, type); } var c1 = Expression.GreaterThanOrEqual(nonNullProperty, constantFrom); var c2 = Expression.LessThanOrEqual(nonNullProperty, constantTo); var c = Expression.AndAlso(c1, c2); q.AppendExpression(c); return(q); }
internal static bool IsIntegerOrBool(Type type) { type = type.GetNonNullableType(); if (!type.IsEnum) { switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: return true; } } return false; }
/// <summary> /// 返回的将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/> /// 类型的用户自定义类型转换。 /// </summary> /// <param name="inputType">要转换的对象的类型。</param> /// <param name="outputType">要将输入对象转换到的类型。</param> /// <returns>将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/> /// 类型的用户自定义类型转换,如果不存在则为 <c>null</c>。</returns> private static Conversion GetUserDefinedConversion(Type inputType, Type outputType) { Contract.Requires(inputType != null && outputType != null && inputType != typeof(void) && outputType != typeof(void)); // 判断可空类型。 Type inputUnderlyingType = inputType.GetNonNullableType(); Type outputUnderlyingType = outputType.GetNonNullableType(); MethodInfo method = UserConversionCache.GetConversion(inputUnderlyingType, outputUnderlyingType); if (method == null) { return null; } Conversion conversion = new UserConversion(method); // 存入缓存。 Type methodInputType = method.GetParametersNoCopy()[0].ParameterType; Tuple<Type, Type> key = new Tuple<Type, Type>(inputType, outputType); if (inputType != methodInputType || outputType != method.ReturnType) { conversion = userDefinedConverers.GetOrAdd(new Tuple<Type, Type>(methodInputType, method.ReturnType), conversion); } if (inputUnderlyingType != inputType || outputUnderlyingType != outputType) { userDefinedConverers.TryAdd(new Tuple<Type, Type>(inputUnderlyingType, outputUnderlyingType), conversion); } if (inputUnderlyingType == inputType || !methodInputType.IsValueType || methodInputType.IsNullable()) { return userDefinedConverers.GetOrAdd(key, conversion); } // 需要将输入的 Nullable<T> 解包。 if (outputUnderlyingType != outputType || !outputType.IsValueType) { // outputType 可以为 null(引用类型或 Nullable<T>)。 return userDefinedConverers.GetOrAdd(key, BetweenNullableConversion.UserDefined); } return userDefinedConverers.GetOrAdd(key, FromNullableConversion.UserDefined); }
public static bool CanEdit(Type type) { Debug.Assert(type != null); type = type.GetNonNullableType(); return type.IsEnum || type == typeof(System.String) || type == typeof(System.Char) || type == typeof(System.DateTime) || type == typeof(System.Boolean) || type == typeof(System.Byte) || type == typeof(System.SByte) || type == typeof(System.Single) || type == typeof(System.Double) || type == typeof(System.Decimal) || type == typeof(System.Int16) || type == typeof(System.Int32) || type == typeof(System.Int64) || type == typeof(System.UInt16) || type == typeof(System.UInt32) || type == typeof(System.UInt64); }
internal static object Convert(IBindingMemberInfo member, Type type, object value) { if (value == null) { if (type.IsValueType() && !type.IsNullableType()) return Activator.CreateInstance(type); return null; } if (type.IsInstanceOfType(value)) return value; #if WPF || ANDROID || TOUCH || WINFORMS || WINDOWS_PHONE || SILVERLIGHT var converter = GetTypeConverter(type, member.Member); if (converter != null && converter.CanConvertFrom(value.GetType())) return converter.ConvertFrom(value); #endif #if PCL_WINRT if (TypeCodeTable.ContainsKey(value.GetType())) #else if (value is IConvertible) #endif return System.Convert.ChangeType(value, type.GetNonNullableType(), CultureInfo.CurrentCulture); if (type == typeof(string)) return value.ToString(); return value; }
internal static MethodInfo GetUserDefinedCoercionMethod(Type convertFrom, Type convertToType, bool implicitOnly) { Type nonNullableType = convertFrom.GetNonNullableType(); Type type2 = convertToType.GetNonNullableType(); MethodInfo[] methods = nonNullableType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); MethodInfo info = FindConversionOperator(methods, convertFrom, convertToType, implicitOnly); if (info != null) { return info; } MethodInfo[] infoArray2 = type2.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); info = FindConversionOperator(infoArray2, convertFrom, convertToType, implicitOnly); if (info != null) { return info; } if (!AreEquivalent(nonNullableType, convertFrom) || !AreEquivalent(type2, convertToType)) { info = FindConversionOperator(methods, nonNullableType, type2, implicitOnly); if (info == null) { info = FindConversionOperator(infoArray2, nonNullableType, type2, implicitOnly); } if (info != null) { return info; } } return null; }
// initialize auto column properties based on data type void InitializeAutoColumn(Column c, Type type) { // save column type c.DataType = type; // handle nullable types type = type.GetNonNullableType(); // initialize column properties based on type if (type == typeof(string)) { c.Width = new GridLength(180); } else if (type.IsNumericIntegral()) { c.Width = new GridLength(80); c.Format = "n0"; } else if (type.IsNumericNonIntegral()) { c.Width = new GridLength(80); c.Format = "n2"; } else if (type == typeof(bool)) { c.Width = new GridLength(60); } else if (type == typeof(DateTime)) { c.Format = "d"; } }
private static bool AlignRight(Row r, Column c, Type t) { if (r is GroupRow && c.Grid != null && c.Index <= c.Grid.Columns.FirstVisibleIndex) { return false; } if (t.GetNonNullableType().IsNumeric()) { ColumnValueConverter converter = c.ValueConverter as ColumnValueConverter; if (converter == null || converter.Values == null) { return true; } } return false; }
private static bool IsImplicitNullableConversion(Type source, Type destination) { return (destination.IsNullableType() && IsImplicitlyConvertible(source.GetNonNullableType(), destination.GetNonNullableType())); }
/// <summary> /// If the result of an isinst opcode is known statically, this /// returns the result, otherwise it returns null, meaning we'll need /// to perform the IsInst instruction at runtime. /// /// The result of this function must be equivalent to IsInst, or /// null. /// </summary> private static AnalyzeTypeIsResult AnalyzeTypeIs(Expression operand, Type testType) { Type operandType = operand.Type; // Oddly, we allow void operands // This is LinqV1 behavior of TypeIs if (operandType == typeof(void)) { return AnalyzeTypeIsResult.KnownFalse; } // // Type comparisons treat nullable types as if they were the // underlying type. The reason is when you box a nullable it // becomes a boxed value of the underlying type, or null. // Type nnOperandType = operandType.GetNonNullableType(); Type nnTestType = testType.GetNonNullableType(); // // See if we can determine the answer based on the static types // // Extensive testing showed that Type.IsAssignableFrom, // Type.IsInstanceOfType, and the isinst instruction were all // equivalent when used against a live object // if (nnTestType.IsAssignableFrom(nnOperandType)) { // If the operand is a value type (other than nullable), we // know the result is always true. if (operandType.IsValueType && !operandType.IsNullableType()) { return AnalyzeTypeIsResult.KnownTrue; } // For reference/nullable types, we need to compare to null at runtime return AnalyzeTypeIsResult.KnownAssignable; } // // If we couldn't statically assign and the type is sealed, no // value at runtime can make isinst succeed // if (nnOperandType.IsSealed) { return AnalyzeTypeIsResult.KnownFalse; } // Otherwise we need a full runtime check return AnalyzeTypeIsResult.Unknown; }
internal static bool IsFloatingPoint(Type type) { type = type.GetNonNullableType(); switch (Type.GetTypeCode(type)) { case TypeCode.Single: case TypeCode.Double: return true; } return false; }
internal static bool IsConvertible(Type type) { type = type.GetNonNullableType(); if (type.IsEnum) { return true; } switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: return true; } return false; }
internal static bool HasReferenceConversion(Type source, Type dest) { if ((source == typeof(void)) || (dest == typeof(void))) { return false; } Type nonNullableType = source.GetNonNullableType(); Type c = dest.GetNonNullableType(); if (!nonNullableType.IsAssignableFrom(c)) { if (c.IsAssignableFrom(nonNullableType)) { return true; } if (source.IsInterface || dest.IsInterface) { return true; } if (!IsLegalExplicitVariantDelegateConversion(source, dest) && (!(source == typeof(object)) && !(dest == typeof(object)))) { return false; } } return true; }
internal static bool HasIdentityPrimitiveOrNullableConversion(Type source, Type dest) { return (AreEquivalent(source, dest) || ((source.IsNullableType() && AreEquivalent(dest, source.GetNonNullableType())) || ((dest.IsNullableType() && AreEquivalent(source, dest.GetNonNullableType())) || ((IsConvertible(source) && IsConvertible(dest)) && (dest.GetNonNullableType() != typeof(bool)))))); }
internal static bool HasBuiltInEqualityOperator(Type left, Type right) { if (!left.IsInterface || right.IsValueType) { if (right.IsInterface && !left.IsValueType) { return true; } if ((!left.IsValueType && !right.IsValueType) && (AreReferenceAssignable(left, right) || AreReferenceAssignable(right, left))) { return true; } if (!AreEquivalent(left, right)) { return false; } Type nonNullableType = left.GetNonNullableType(); if ((!(nonNullableType == typeof(bool)) && !IsNumeric(nonNullableType)) && !nonNullableType.IsEnum) { return false; } } return true; }
private static Expression CreateValueExpression(Type targetType, object value, CultureInfo culture) { if (((targetType != typeof(string)) && (!targetType.IsValueType || targetType.IsNullableType())) && (string.Compare(value as string, "null", StringComparison.OrdinalIgnoreCase) == 0)) { value = null; } if (value != null) { Type nonNullableTargetType = targetType.GetNonNullableType(); if (value.GetType() != nonNullableTargetType) { if (nonNullableTargetType.IsEnum) { value = Enum.Parse(nonNullableTargetType, value.ToString(), true); } else if (value is IConvertible) { value = Convert.ChangeType(value, nonNullableTargetType, culture); } } } return CreateConstantExpression(value); }
internal static bool IsUnsigned(Type type) { type = type.GetNonNullableType(); switch (Type.GetTypeCode(type)) { case TypeCode.Char: case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return true; } return false; }
internal static bool IsUnsignedInt(Type type) { type = type.GetNonNullableType(); if (!type.IsEnum) { switch (Type.GetTypeCode(type)) { case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return true; } } return false; }
internal static object Convert(IBindingMemberInfo member, Type type, object value) { if (value == null) return type.GetDefaultValue(); if (type.IsInstanceOfType(value)) return value; #if PCL_WINRT if (type.GetTypeInfo().IsEnum && value is string) #else if (type.IsEnum && value is string) #endif return Enum.Parse(type, (string)value, false); #if WPF || ANDROID || TOUCH || WINFORMS || WINDOWS_PHONE || SILVERLIGHT var converter = GetTypeConverter(type, member.Member); if (converter != null && converter.CanConvertFrom(value.GetType())) return converter.ConvertFrom(value); #endif #if PCL_WINRT if (TypeCodeTable.ContainsKey(value.GetType())) #else if (value is IConvertible) #endif return System.Convert.ChangeType(value, type.GetNonNullableType(), BindingServiceProvider.BindingCultureInfo()); if (type == typeof(string)) return value.ToString(); return value; }
private bool TypesArePrimitiveAndConvertible(Type source, Type dest) { Type nonNullableSourceType = source.GetNonNullableType(); Type nonNullableDestinationType = dest.GetNonNullableType(); return (!(source.IsEnum || dest.IsEnum)) && (source.IsEquivalentTo(dest) || ((source.IsNullableType() && dest.IsEquivalentTo(nonNullableSourceType)) || ((dest.IsNullableType() && source.IsEquivalentTo(nonNullableDestinationType)) || ((source.IsNumeric() && dest.IsNumeric()) && (nonNullableDestinationType != TypeSystem.Boolean))))); }
public static bool IsCompatibleWith(this Type source, Type target) { if (source == target) { return(true); } if (!target.IsValueType) { return(target.IsAssignableFrom(source)); } Type st = source.GetNonNullableType(); Type tt = target.GetNonNullableType(); if (st != source && tt == target) { return(false); } TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st); TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt); switch (sc) { case TypeCode.SByte: switch (tc) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.Byte: switch (tc) { case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.Int16: switch (tc) { case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.UInt16: switch (tc) { case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.Int32: switch (tc) { case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.UInt32: switch (tc) { case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.Int64: switch (tc) { case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.UInt64: switch (tc) { case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return(true); } break; case TypeCode.Single: switch (tc) { case TypeCode.Single: case TypeCode.Double: return(true); } break; default: if (st == tt) { return(true); } break; } return(false); }
static void WriteSerializerBytesToStream(ILGenerator il, Type type, OpCode valueOpCode, int valueLocalIndex, int tag, MethodInfo valueMethod, bool isTargetCollection) { var isTypeEnum = type.IsEnum; il.Emit(OpCodes.Ldarg_1); il.Emit(valueOpCode, valueLocalIndex); if (valueMethod != null) il.Emit(OpCodes.Call, valueMethod);//Virt if (type.IsNullable()) il.Emit(OpCodes.Call, type.GetNullableValueMethod()); if (isTypeEnum) il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Ldc_I4, tag); if (isTypeEnum) type = EnumType; il.Emit(OpCodes.Ldc_I4, isTargetCollection ? 1 : 0); il.Emit(OpCodes.Call, PrimitiveWriterMethods[type.GetNonNullableType()]); }
private static void InitializeAutoColumn(Column c, Type type) { c.DataType = type; type = type.GetNonNullableType(); if (type == typeof (string)) { c.Width = new GridLength(180); return; } if (type.IsNumericIntegral()) { c.Width = new GridLength(80); c.Format = "n0"; return; } if (type.IsNumericNonIntegral()) { c.Width = new GridLength(80); c.Format = "n2"; return; } if (type == typeof (bool)) { c.Width = new GridLength(60); return; } if (type == typeof (DateTime)) { c.Format = "d"; } }
internal static bool IsBool(Type type) { return (type.GetNonNullableType() == typeof(bool)); }
/// <summary> /// Determine if the <paramref name="source"/> type can be converted /// to the <paramref name="target"/> type. /// </summary> /// <param name="source">The source type.</param> /// <param name="target">The desired target type.</param> /// <returns>Whether or not the source <see cref="Type"/> can be /// converted to the target <see cref="Type"/>.</returns> private static bool IsSupportedConversion(Type source, Type target) { if (source == target) { return true; } if (!target.IsValueType) { return target.IsAssignableFrom(source); } Type coreSource = source.GetNonNullableType(); Type coreTarget = target.GetNonNullableType(); // If the source is nullable, but the target isn't, // then we cannot convert. if (coreSource != source && coreTarget == target) { return false; } // Enums will be compared using the underlying type if (coreSource.IsEnum) { coreSource = Enum.GetUnderlyingType(coreSource); } if (coreTarget.IsEnum) { coreTarget = Enum.GetUnderlyingType(coreTarget); } return (coreSource == coreTarget) || (supportedConversions.ContainsKey(coreSource) && supportedConversions[coreSource].Contains(coreTarget)); }
internal static bool IsCompatibleWith(this Type source, Type target) { if (source == target) return true; if (!target.IsValueType) return target.IsAssignableFrom(source); Type st = source.GetNonNullableType(); Type tt = target.GetNonNullableType(); if (st != source && tt == target) return false; TypeCode sc = st.IsEnum ? TypeCode.Object : Type.GetTypeCode(st); TypeCode tc = tt.IsEnum ? TypeCode.Object : Type.GetTypeCode(tt); switch (sc) { case TypeCode.SByte: switch (tc) { case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Byte: switch (tc) { case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Int16: switch (tc) { case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt16: switch (tc) { case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Int32: switch (tc) { case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt32: switch (tc) { case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Int64: switch (tc) { case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.UInt64: switch (tc) { case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: return true; } break; case TypeCode.Single: switch (tc) { case TypeCode.Single: case TypeCode.Double: return true; } break; default: if (st == tt) return true; break; } return false; }
static void WriteDeserializerReadValue(TypeBuilder typeBuilder, ILGenerator il, Type type, int tag, int itemLocalIndex) { var isCollection = type.IsCollectionType(); var isClass = !isCollection && type.IsComplexType(); if (isClass) { MethodBuilder method; var hasTypeMapping = TypeMapping.ContainsKey(type); if (hasTypeMapping) { var index = 0; var typeMapping = TypeMapping[type]; var count = typeMapping.Count; var types = typeMapping.Select(kv => kv.Key); var needBranchLabel = count > 1; var branchLabel = needBranchLabel ? il.DefineLabel() : DefaultLabel; var valueTypeLocal = il.DeclareLocal(TypeType); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldtoken, type); il.Emit(OpCodes.Call, GetTypeFromHandleMethod); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, ConvertBaseToConcreteTypeMethod); il.Emit(OpCodes.Stloc, valueTypeLocal.LocalIndex); foreach (var mapType in types) { index++; var isLastIndex = index == count; var isLastCondition = isLastIndex && needBranchLabel; var conditionLabel = !isLastCondition ? il.DefineLabel() : DefaultLabel; var currentConditionLabel = isLastCondition ? branchLabel : conditionLabel; il.Emit(OpCodes.Ldloc, valueTypeLocal.LocalIndex); il.Emit(OpCodes.Ldtoken, mapType); il.Emit(OpCodes.Call, GetTypeFromHandleMethod); il.Emit(OpCodes.Call, GetTypeOpEqualityMethod); il.Emit(OpCodes.Brfalse, currentConditionLabel); method = GenerateDeserializerClass(typeBuilder, mapType); il.Emit(OpCodes.Newobj, mapType.GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Stloc, itemLocalIndex); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc, itemLocalIndex); if (mapType.IsClass) il.Emit(OpCodes.Castclass, mapType); else il.Emit(OpCodes.Unbox_Any, mapType); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, method); if (!isLastIndex) il.Emit(OpCodes.Br, branchLabel); il.MarkLabel(currentConditionLabel); } } else { method = GenerateDeserializerClass(typeBuilder, type); var isTypeClass = type.IsClass; if (isTypeClass) { il.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Stloc, itemLocalIndex); } else { il.Emit(OpCodes.Ldloca, itemLocalIndex); il.Emit(OpCodes.Initobj, type); } il.Emit(OpCodes.Ldarg_0); if (isTypeClass) il.Emit(OpCodes.Ldloc, itemLocalIndex); else il.Emit(OpCodes.Ldloca, itemLocalIndex); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, method); } } else if (isCollection) { WriteDeserializerClass(typeBuilder, il, type, tag, null, itemLocalIndex: itemLocalIndex); } else { var nonNullableType = type.GetNonNullableType(); var isTypeEnum = type.IsEnum; var needTypeForReader = PrimitiveReadersWithTypes.Contains(isTypeEnum ? EnumType : nonNullableType); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Ldc_I4, 1); il.Emit(OpCodes.Ldc_I4, type.IsBufferedTypeInt()); il.Emit(OpCodes.Call, ReadNextBytesMethod); if (needTypeForReader) { il.Emit(OpCodes.Ldtoken, type); il.Emit(OpCodes.Call, GetTypeFromHandleMethod); } if (isTypeEnum) il.Emit(OpCodes.Call, PrimitiveReaderMethods[EnumType]); else { il.Emit(OpCodes.Call, PrimitiveReaderMethods[nonNullableType]); if (type.IsNullable()) il.Emit(OpCodes.Newobj, type.GetNullableTypeCtor()); } if (needTypeForReader) il.Emit(OpCodes.Unbox_Any, type); il.Emit(OpCodes.Stloc, itemLocalIndex); } }