Beispiel #1
0
 /// <summary>
 /// Tells Insight the custom serializer to use when serializing all instances of type T.
 /// </summary>
 /// <typeparam name="T">The type that is being serialized.</typeparam>
 /// <param name="serializer">The serializer to use.</param>
 public static void Serialize <T>(IDbObjectSerializer serializer)
 {
     AddRule(new DbSerializationRule()
     {
         FieldType = typeof(T), Mode = SerializationMode.Custom, Serializer = serializer
     });
 }
Beispiel #2
0
 /// <summary>
 /// Tells Insight the SerializationMode to use when serializing the given member of type T.
 /// </summary>
 /// <typeparam name="T">The type containing the object to be serialized.</typeparam>
 /// <param name="fieldName">The name of the field.</param>
 /// <param name="serializer">The serializer to use.</param>
 public static void Serialize <T>(string fieldName, IDbObjectSerializer serializer)
 {
     AddRule(new DbSerializationRule()
     {
         RecordType = typeof(T), FieldName = fieldName, Mode = SerializationMode.Custom, Serializer = serializer
     });
 }
		/// <summary>
		/// Initializes a new instance of the FieldMapping class.
		/// </summary>
		/// <param name="pathToMember">The path to the member.</param>
		/// <param name="member">The member that is bound.</param>
		/// <param name="serializer">The serializer for the mapping.</param>
		public FieldMapping(string pathToMember, ClassPropInfo member, IDbObjectSerializer serializer)
		{
			PathToMember = pathToMember;
			Member = member;
			Serializer = serializer;
			Prefix = ClassPropInfo.GetMemberPrefix(pathToMember);
			IsDeep = (Prefix != null);
		}
 /// <summary>
 /// Initializes a new instance of the FieldMapping class.
 /// </summary>
 /// <param name="pathToMember">The path to the member.</param>
 /// <param name="member">The member that is bound.</param>
 /// <param name="serializer">The serializer for the mapping.</param>
 public FieldMapping(string pathToMember, ClassPropInfo member, IDbObjectSerializer serializer)
 {
     PathToMember = pathToMember;
     Member       = member;
     Serializer   = serializer;
     Prefix       = ClassPropInfo.GetMemberPrefix(pathToMember);
     IsDeep       = (Prefix != null);
 }
Beispiel #5
0
        /// <summary>
        /// Look up a DbType from a .Net type.
        /// </summary>
        /// <param name="type">The type of object to look up.</param>
        /// <param name="serializer">The serializer that has been detected for the field.</param>
        /// <param name="parameterType">The expected sql parameter type. Used as the default.</param>
        /// <returns>The equivalent DbType.</returns>
        private static DbType LookupDbType(Type type, IDbObjectSerializer serializer, DbType parameterType)
        {
            DbType sqlType;

            // if the serializer can serialize it, then it's a string
            if (serializer != null && serializer.CanSerialize(type, parameterType))
            {
                return(serializer.GetSerializedDbType(type, parameterType));
            }

            // if the type is nullable, get the underlying type
            var nullUnderlyingType = Nullable.GetUnderlyingType(type);

            if (nullUnderlyingType != null)
            {
                type = nullUnderlyingType;
            }

            // if it's an enum, get the underlying type
            if (type.GetTypeInfo().IsEnum)
            {
                type = Enum.GetUnderlyingType(type);
            }

            // look up the type
            if (_typeToDbTypeMap.TryGetValue(type, out sqlType))
            {
                return(sqlType);
            }

            // special cases for XmlDocument and XDocument
            if (type == typeof(XmlDocument))
            {
                return(DbType.Xml);
            }
            if (type == typeof(XDocument))
            {
                return(DbType.Xml);
            }

            // support for enumerables
            if (typeof(IEnumerable).IsAssignableFrom(type))
            {
                // use -1 to denote its a list, hacky but will work on any DB
                return(DbTypeEnumerable);
            }

            // sql udts are udts
            if (TypeHelper.IsSqlUserDefinedType(type))
            {
                return(DbType.Object);
            }

            // let's see if the type can be directly converted to the parameter type
            return(parameterType);
        }
Beispiel #6
0
 /// <summary>
 /// Serializes an object. This is a stub method that reorders parameters.
 /// </summary>
 /// <param name="value">The value to serialize.</param>
 /// <param name="type">The type to serialize.</param>
 /// <param name="serializer">The serializer to use.</param>
 /// <returns>The serialized object.</returns>
 private static object SerializeObject(object value, Type type, IDbObjectSerializer serializer)
 {
     return(serializer.SerializeObject(type, value));
 }
Beispiel #7
0
 /// <summary>
 /// Serialize a value into a parameter. This is a stub method that reorders the stack.
 /// </summary>
 /// <param name="value">The value to serialize.</param>
 /// <param name="type">The type of the member.</param>
 /// <param name="serializer">The serializer to use.</param>
 /// <returns>The serialized value.</returns>
 private static object SerializeParameterValue(object value, Type type, IDbObjectSerializer serializer)
 {
     return(serializer.SerializeObject(type, value) ?? DBNull.Value);
 }
		/// <summary>
		/// Serializes an object. This is a stub method that reorders parameters.
		/// </summary>
		/// <param name="value">The value to serialize.</param>
		/// <param name="type">The type to serialize.</param>
		/// <param name="serializer">The serializer to use.</param>
		/// <returns>The serialized object.</returns>
		private static object SerializeObject(object value, Type type, IDbObjectSerializer serializer)
		{
			return serializer.SerializeObject(type, value);
		}
		/// <summary>
		/// Look up a DbType from a .Net type.
		/// </summary>
		/// <param name="type">The type of object to look up.</param>
		/// <param name="serializer">The serializer that has been detected for the field.</param>
		/// <param name="parameterType">The expected sql parameter type. Used as the default.</param>
		/// <returns>The equivalend DbType.</returns>
		private static DbType LookupDbType(Type type, IDbObjectSerializer serializer, DbType parameterType)
		{
			DbType sqlType;

            // if the serializer can serialize it, then it's a string
            if (serializer != null && serializer.CanSerialize(type, parameterType))
                return serializer.GetSerializedDbType(type, parameterType);

			// if the type is nullable, get the underlying type
			var nullUnderlyingType = Nullable.GetUnderlyingType(type);
			if (nullUnderlyingType != null)
				type = nullUnderlyingType;

			// if it's an enum, get the underlying type
			if (type.IsEnum)
				type = Enum.GetUnderlyingType(type);

			// look up the type
			if (_typeToDbTypeMap.TryGetValue(type, out sqlType))
				return sqlType;

			// special cases for XmlDocument and XDocument
			if (type == typeof(XmlDocument))
				return DbType.Xml;
			if (type == typeof(XDocument))
				return DbType.Xml;

			// support for enumerables
			if (typeof(IEnumerable).IsAssignableFrom(type))
			{
				// use -1 to denote its a list, hacky but will work on any DB
				return DbTypeEnumerable;
			}

			// sql udts are udts
			if (TypeHelper.IsSqlUserDefinedType(type))
				return DbType.Object;

			// let's see if the type can be directly converted to the parameter type
			return parameterType;
		}
		/// <summary>
		/// Serialize a value into a parameter. This is a stub method that reorders the stack.
		/// </summary>
		/// <param name="value">The value to serialize.</param>
		/// <param name="type">The type of the member.</param>
		/// <param name="serializer">The serializer to use.</param>
		/// <returns>The serialized value.</returns>
		private static object SerializeParameterValue(object value, Type type, IDbObjectSerializer serializer)
		{
			return serializer.SerializeObject(type, value) ?? DBNull.Value;
		}
        /// <summary>
        /// Emits the IL to convert a value to a target type.
        /// </summary>
        /// <param name="il">The IL generator to output to.</param>
        /// <param name="memberName">The name of the member being converted.</param>
        /// <param name="sourceType">The source type.</param>
        /// <param name="targetType">The target type.</param>
        /// <param name="serializer">The serializer to use to deserialize the value.</param>
        public static void EmitConvertValue(ILGenerator il, string memberName, Type sourceType, Type targetType, IDbObjectSerializer serializer)
        {
            // targetType - the target type we need to convert to
            // underlyingTargetType - if the target type is nullable, we need to look at the underlying target type
            // rawTargetType - if the underlying target type is enum, we need to look at the underlying target type for that
            // sourceType - this is the type of the data in the data set
            Type underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            // some labels that we need
            var finishLabel = il.DefineLabel();
            Label isDbNullLabel = il.DefineLabel();

            // if the value is DbNull, then we continue to the next item
            il.Emit(OpCodes.Dup);								// dup value, stack => [target][value][value]
            il.Emit(OpCodes.Isinst, typeof(DBNull));			// isinst DBNull:value, stack => [target][value-as-object][DBNull or null]
            il.Emit(OpCodes.Brtrue_S, isDbNullLabel);			// br.true isDBNull, stack => [target][value-as-object]

            // handle the special target types first
            if (targetType == typeof(char))
            {
                // char
                il.EmitCall(OpCodes.Call, _readChar, null);
            }
            else if (targetType == typeof(char?))
            {
                // char?
                il.EmitCall(OpCodes.Call, _readNullableChar, null);
            }
            else if (targetType == TypeHelper.LinqBinaryType)
            {
                // unbox sql byte arrays to Linq.Binary

                // before: stack => [target][object-value]
                // after: stack => [target][byte-array-value]
                il.Emit(OpCodes.Unbox_Any, typeof(byte[])); // stack is now [target][byte-array]
                // before: stack => [target][byte-array-value]
                // after: stack => [target][Linq.Binary-value]
                il.Emit(OpCodes.Newobj, TypeHelper.LinqBinaryCtor);
            }
            else if (targetType == typeof(XmlDocument))
            {
                // special handler for XmlDocuments

                // before: stack => [target][object-value]
                il.Emit(OpCodes.Call, _readXmlDocument);

                // after: stack => [target][xmlDocument]
            }
            else if (targetType == typeof(XDocument))
            {
                // special handler for XDocuments

                // before: stack => [target][object-value]
                il.Emit(OpCodes.Call, _readXDocument);

                // after: stack => [target][xDocument]
            }
            else if (serializer != null && serializer.CanDeserialize(sourceType, targetType))
            {
                // we are getting a string from the database, but the target is not a string, and it's a reference type
                // assume the column is a serialized data type and that we want to deserialize it
                il.EmitLoadType(targetType);
                StaticFieldStorage.EmitLoad(il, serializer);
                il.Emit(OpCodes.Call, typeof(TypeConverterGenerator).GetMethod("DeserializeObject", BindingFlags.NonPublic | BindingFlags.Static));
                il.Emit(OpCodes.Unbox_Any, targetType);
            }
            else if (underlyingTargetType.IsEnum && sourceType == typeof(string))
            {
                var localString = il.DeclareLocal(typeof(string));

                // if we are converting a string to an enum, then parse it.
                // see if the value from the database is a string. if so, we need to parse it. If not, we will just try to unbox it.
                il.Emit(OpCodes.Isinst, typeof(string));			// is string, stack => [target][string]
                il.Emit(OpCodes.Stloc, localString);				// pop loc.2 (enum), stack => [target]

                // call enum.parse (type, value, true)
                il.EmitLoadType(underlyingTargetType);
                il.Emit(OpCodes.Ldloc, localString);				// push enum, stack => [target][enum-type][string]
                il.Emit(OpCodes.Ldc_I4_1);							// push true, stack => [target][enum-type][string][true]
                il.EmitCall(OpCodes.Call, _enumParse, null);		// call Enum.Parse, stack => [target][enum-as-object]

                // Enum.Parse returns an object, which we need to unbox to the enum value
                il.Emit(OpCodes.Unbox_Any, underlyingTargetType);
            }
            else if (EmitConstructorConversion(il, sourceType, targetType))
            {
                // target type can be constructed from source type
            }
            else
            {
                // this isn't a system value type, so unbox to the type the reader is giving us (this is a system type, hopefully)
                // now we have an unboxed sourceType
                il.Emit(OpCodes.Unbox_Any, sourceType);

                if (sourceType != targetType)
                {
                    // attempt to convert the value to the target type
                    if (!EmitConversionOrCoersion(il, sourceType, targetType))
                    {
                        if (sourceType != targetType)
                        {
                            throw new InvalidOperationException(String.Format(
                                CultureInfo.InvariantCulture,
                                "Field {0} cannot be converted from {1} to {2}. Create a conversion constructor or conversion operator.",
                                memberName,
                                sourceType.AssemblyQualifiedName,
                                targetType.AssemblyQualifiedName));
                        }
                    }

                    // if the target is nullable, then construct the nullable from the data
                    if (Nullable.GetUnderlyingType(targetType) != null)
                        il.Emit(OpCodes.Newobj, targetType.GetConstructor(new[] { underlyingTargetType }));
                }
            }

            /////////////////////////////////////////////////////////////////////
            // convert DBNull to default of the given type
            il.Emit(OpCodes.Br_S, finishLabel);
            il.MarkLabel(isDbNullLabel);
            il.Emit(OpCodes.Pop);
            TypeHelper.EmitDefaultValue(il, targetType);

            il.MarkLabel(finishLabel);
        }
		/// <summary>
		/// Deserializes an object. This is a stub method that just reorders the parameters.
		/// </summary>
		/// <param name="encoded">The encoded value.</param>
		/// <param name="type">The type to deserialize.</param>
		/// <param name="serializer">The serializer to use.</param>
		/// <returns>The deserialized object.</returns>
		private static object DeserializeObject(object encoded, Type type, IDbObjectSerializer serializer)
		{
			return serializer.DeserializeObject(type, encoded);
		}
Beispiel #13
0
        /// <summary>
        /// Emits the IL to convert a value to a target type.
        /// </summary>
        /// <param name="il">The IL generator to output to.</param>
        /// <param name="memberName">The name of the member being converted.</param>
        /// <param name="sourceType">The source type.</param>
        /// <param name="targetType">The target type.</param>
        /// <param name="serializer">The serializer to use to deserialize the value.</param>
        public static void EmitConvertValue(ILGenerator il, string memberName, Type sourceType, Type targetType, IDbObjectSerializer serializer)
        {
            // targetType - the target type we need to convert to
            // underlyingTargetType - if the target type is nullable, we need to look at the underlying target type
            // rawTargetType - if the underlying target type is enum, we need to look at the underlying target type for that
            // sourceType - this is the type of the data in the data set
            Type underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            // some labels that we need
            var   finishLabel   = il.DefineLabel();
            Label isDbNullLabel = il.DefineLabel();

            // if the value is DbNull, then we continue to the next item
            il.Emit(OpCodes.Dup);                                       // dup value, stack => [target][value][value]
            il.Emit(OpCodes.Isinst, typeof(DBNull));                    // isinst DBNull:value, stack => [target][value-as-object][DBNull or null]
            il.Emit(OpCodes.Brtrue_S, isDbNullLabel);                   // br.true isDBNull, stack => [target][value-as-object]

            // handle the special target types first
            if (targetType == typeof(char))
            {
                // char
                il.EmitCall(OpCodes.Call, _readChar, null);
            }
            else if (targetType == typeof(char?))
            {
                // char?
                il.EmitCall(OpCodes.Call, _readNullableChar, null);
            }
            else if (targetType == TypeHelper.LinqBinaryType)
            {
                // unbox sql byte arrays to Linq.Binary

                // before: stack => [target][object-value]
                // after: stack => [target][byte-array-value]
                il.Emit(OpCodes.Unbox_Any, typeof(byte[])); // stack is now [target][byte-array]
                // before: stack => [target][byte-array-value]
                // after: stack => [target][Linq.Binary-value]
                il.Emit(OpCodes.Newobj, TypeHelper.LinqBinaryCtor);
            }
            else if (targetType == typeof(XmlDocument))
            {
                // special handler for XmlDocuments

                // before: stack => [target][object-value]
                il.Emit(OpCodes.Call, _readXmlDocument);

                // after: stack => [target][xmlDocument]
            }
            else if (targetType == typeof(XDocument))
            {
                // special handler for XDocuments

                // before: stack => [target][object-value]
                il.Emit(OpCodes.Call, _readXDocument);

                // after: stack => [target][xDocument]
            }
            else if (serializer != null && serializer.CanDeserialize(sourceType, targetType))
            {
                // we are getting a string from the database, but the target is not a string, and it's a reference type
                // assume the column is a serialized data type and that we want to deserialize it
                il.EmitLoadType(targetType);
                StaticFieldStorage.EmitLoad(il, serializer);
                il.Emit(OpCodes.Call, typeof(TypeConverterGenerator).GetMethod("DeserializeObject", BindingFlags.NonPublic | BindingFlags.Static));
                il.Emit(OpCodes.Unbox_Any, targetType);
            }
            else if (underlyingTargetType.IsEnum && sourceType == typeof(string))
            {
                var localString = il.DeclareLocal(typeof(string));

                // if we are converting a string to an enum, then parse it.
                // see if the value from the database is a string. if so, we need to parse it. If not, we will just try to unbox it.
                il.Emit(OpCodes.Isinst, typeof(string));                        // is string, stack => [target][string]
                il.Emit(OpCodes.Stloc, localString);                            // pop loc.2 (enum), stack => [target]

                // call enum.parse (type, value, true)
                il.EmitLoadType(underlyingTargetType);
                il.Emit(OpCodes.Ldloc, localString);                    // push enum, stack => [target][enum-type][string]
                il.Emit(OpCodes.Ldc_I4_1);                              // push true, stack => [target][enum-type][string][true]
                il.EmitCall(OpCodes.Call, _enumParse, null);            // call Enum.Parse, stack => [target][enum-as-object]

                // Enum.Parse returns an object, which we need to unbox to the enum value
                il.Emit(OpCodes.Unbox_Any, underlyingTargetType);
            }
            else if (EmitConstructorConversion(il, sourceType, targetType))
            {
                // target type can be constructed from source type
            }
            else
            {
                // this isn't a system value type, so unbox to the type the reader is giving us (this is a system type, hopefully)
                // now we have an unboxed sourceType
                il.Emit(OpCodes.Unbox_Any, sourceType);

                if (sourceType != targetType)
                {
                    // attempt to convert the value to the target type
                    if (!EmitConversionOrCoersion(il, sourceType, targetType))
                    {
                        if (sourceType != targetType)
                        {
                            throw new InvalidOperationException(String.Format(
                                                                    CultureInfo.InvariantCulture,
                                                                    "Field {0} cannot be converted from {1} to {2}. Create a conversion constructor or conversion operator.",
                                                                    memberName,
                                                                    sourceType.AssemblyQualifiedName,
                                                                    targetType.AssemblyQualifiedName));
                        }
                    }

                    // if the target is nullable, then construct the nullable from the data
                    if (Nullable.GetUnderlyingType(targetType) != null)
                    {
                        il.Emit(OpCodes.Newobj, targetType.GetConstructor(new[] { underlyingTargetType }));
                    }
                }
            }

            /////////////////////////////////////////////////////////////////////
            // convert DBNull to default of the given type
            il.Emit(OpCodes.Br_S, finishLabel);
            il.MarkLabel(isDbNullLabel);
            il.Emit(OpCodes.Pop);
            TypeHelper.EmitDefaultValue(il, targetType);

            il.MarkLabel(finishLabel);
        }
Beispiel #14
0
 /// <summary>
 /// Deserializes an object. This is a stub method that just reorders the parameters.
 /// </summary>
 /// <param name="encoded">The encoded value.</param>
 /// <param name="type">The type to deserialize.</param>
 /// <param name="serializer">The serializer to use.</param>
 /// <returns>The deserialized object.</returns>
 private static object DeserializeObject(object encoded, Type type, IDbObjectSerializer serializer)
 {
     return(serializer.DeserializeObject(type, encoded));
 }