private void CreateProperty(TypeBuilderHelper typeBuilderHelper)
        {
            var dbObjectContainerField  = typeBuilderHelper.DefineField("dbObjectContainer", typeof(DbObjectContainer), FieldAttributes.Private);
            var objectContainerProperty = typeBuilderHelper.TypeBuilder.DefineProperty("DbObjectContainer",
                                                                                       PropertyAttributes.HasDefault,
                                                                                       typeof(DbObjectContainer),
                                                                                       new[] { typeof(DbObjectContainer) });
            var attributes = MethodAttributes.Public | MethodAttributes.SpecialName |
                             MethodAttributes.HideBySig;
            var objectContainerGetMethod = typeBuilderHelper.DefineMethod("get_DbObjectContainer",
                                                                          attributes, typeof(DbObjectContainer), Type.EmptyTypes);
            var objectContainerGetMethodEmit = objectContainerGetMethod.Emitter;

            objectContainerGetMethodEmit
            .ldarg_0
            .ldfld(dbObjectContainerField)
            .ret();

            var objectContainerSetMethod = typeBuilderHelper.DefineMethod("set_DbObjectContainer",
                                                                          attributes, null, typeof(DbObjectContainer));
            var objectContainerSetMethodEmit = objectContainerSetMethod.Emitter;

            objectContainerSetMethodEmit
            .ldarg_0
            .ldarg_1
            .stfld(dbObjectContainerField)
            .ret();
            objectContainerProperty.SetGetMethod(objectContainerGetMethod);
            objectContainerProperty.SetSetMethod(objectContainerSetMethod);
        }
        public static void UpdateType(string typeName, TypeBuilderHelper typeBuilderHelper, FieldInfo[] fieldInfos)
        {
            //Serialize
            var serializerEmit  = typeBuilderHelper.DefineMethod(typeof(ISerializable).GetMethod("Serialize", new Type[] { typeof(BinaryWriter), typeof(IDictionary <object, int>), typeof(int) })).Emitter;
            var deserializeEmit =
                typeBuilderHelper.DefineMethod(typeof(ISerializable).GetMethod("Deserialize", new Type[] { typeof(BinaryReader), typeof(IDictionary <int, object>) })).Emitter;

            //Write type name so we can construct it again
            serializerEmit
            .ldarg_1
            .ldstr(typeName)
            .call(typeof(BinaryWriter).GetMethod("Write", new[] { typeof(string) }))
            //Add current object to the object graph
            .ldarg_2
            .ldarg_0
            .ldarg_3
            .call(typeof(IDictionary <object, int>).GetMethod("Add", new[] { typeof(object), typeof(int) }))
            .ldarg_3
            .ldc_i4_1
            .add
            .starg(3);
            //Serialize/Deserialize properties
            foreach (var fieldInfo in fieldInfos)
            {
                var fieldType = fieldInfo.FieldType;
                if (fieldType.IsPrimitive || fieldType == typeof(string) || fieldType == typeof(DateTime) || fieldType == typeof(decimal))
                {
                    primitiveSerializeEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit);
                }
                else if (fieldType.IsArray)
                {
                    arraySerializeEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit);
                }
                else if (fieldType.IsGenericType && (fieldType.GetGenericTypeDefinition() == typeof(IDictionary <,>) || fieldType.GetGenericTypeDefinition() == typeof(Dictionary <,>)))
                {
                    dictGenericEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit);
                }
                else if (fieldType.IsGenericType && (fieldType.GetGenericTypeDefinition() == typeof(IList <>) || fieldType.GetGenericTypeDefinition() == typeof(List <>)))
                {
                    iListGenericEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit);
                }
                else if (fieldType.IsClass)
                {
                    objectGenericEmitter.Emit(fieldInfo, ref serializerEmit, ref deserializeEmit);
                }
            }
            serializerEmit.ret();
            deserializeEmit.ret();
        }
Example #3
0
        private void BuildTypedSetterForNullable(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType)
        {
            Type       methodType = mi.DeclaringType;
            MethodInfo setMethod  = null;

            if (mi is PropertyInfo)
            {
                setMethod = ((PropertyInfo)mi).GetSetMethod();

                if (setMethod == null)
                {
                    if (_type != _originalType)
                    {
                        setMethod  = _type.GetMethod("set_" + mi.Name);
                        methodType = _type;
                    }

                    if (setMethod == null || !IsMethodAccessible(setMethod))
                    {
                        return;
                    }
                }
            }

            Type       setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType);
            MethodInfo methodInfo =
                _memberAccessor.GetMethod("Set" + setterType.Name, typeof(object), setterType);

            if (methodInfo == null)
            {
                return;
            }

            MethodBuilderHelper method = nestedType.DefineMethod(methodInfo);

            EmitHelper emit = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .ldarg_2
            .newobj(typeof(Nullable <>).MakeGenericType(memberType), memberType)
            .end();

            if (mi is FieldInfo)
            {
                emit.stfld((FieldInfo)mi);
            }
            else
            {
                emit.callvirt(setMethod);
            }

            emit
            .ret()
            ;
        }
Example #4
0
        private void BuildTypedSetter(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType,
            string typedPropertyName)
        {
            Type       methodType = mi.DeclaringType;
            MethodInfo setMethod  = null;

            if (mi is PropertyInfo)
            {
                setMethod = ((PropertyInfo)mi).GetSetMethod();

                if (setMethod == null)
                {
                    if (_type != _originalType)
                    {
                        setMethod  = _type.GetMethod("set_" + mi.Name);
                        methodType = _type;
                    }

                    if (setMethod == null || !IsMethodAccessible(setMethod))
                    {
                        return;
                    }
                }
            }

            MethodInfo methodInfo =
                _memberAccessor.GetMethod("Set" + typedPropertyName, typeof(object), memberType);

            if (methodInfo == null)
            {
                return;
            }

            MethodBuilderHelper method = nestedType.DefineMethod(methodInfo);

            EmitHelper emit = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .ldarg_2
            .end();

            if (mi is FieldInfo)
            {
                emit.stfld((FieldInfo)mi);
            }
            else
            {
                emit.callvirt(setMethod);
            }

            emit
            .ret()
            ;
        }
Example #5
0
        private void BuildTypedGetter(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            string typedPropertyName)
        {
            var methodType = mi.DeclaringType;
            var getMethod  = null as MethodInfo;

            if (mi is PropertyInfo)
            {
                getMethod = ((PropertyInfo)mi).GetGetMethod();

                if (getMethod == null)
                {
                    if (_type != _originalType)
                    {
                        getMethod  = _type.GetMethod("get_" + mi.Name);
                        methodType = _type;
                    }

                    if (getMethod == null || !IsMethodAccessible(getMethod))
                    {
                        return;
                    }
                }
            }

            var methodInfo = _memberAccessor.GetMethod("Get" + typedPropertyName, typeof(object));

            if (methodInfo == null)
            {
                return;
            }

            var method = nestedType.DefineMethod(methodInfo);
            var emit   = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .end();

            if (mi is FieldInfo)
            {
                emit.ldfld((FieldInfo)mi);
            }
            else
            {
                emit.callvirt(getMethod);
            }

            emit
            .ret()
            ;
        }
Example #6
0
        private void BuildTypedGetterForNullable(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType)
        {
            var methodType = mi.DeclaringType;
            var getMethod  = null as MethodInfo;

            if (mi is PropertyInfo)
            {
                getMethod = ((PropertyInfo)mi).GetGetMethod();

                if (getMethod == null)
                {
                    if (_type != _originalType)
                    {
                        getMethod  = _type.GetMethod("get_" + mi.Name);
                        methodType = _type;
                    }

                    if (getMethod == null || !IsMethodAccessible(getMethod))
                    {
                        return;
                    }
                }
            }

            var setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType);
            var methodInfo = _memberAccessor.GetMethod("Get" + setterType.Name, typeof(object));

            if (methodInfo == null)
            {
                return;
            }

            var method       = nestedType.DefineMethod(methodInfo);
            var nullableType = typeof(Nullable <>).MakeGenericType(memberType);
            var emit         = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .end();

            if (mi is FieldInfo)
            {
                emit.ldflda((FieldInfo)mi);
            }
            else
            {
                var locNullable = emit.DeclareLocal(nullableType);

                emit
                .callvirt(getMethod)
                .stloc(locNullable)
                .ldloca(locNullable)
                ;
            }

            emit
            .call(nullableType, "get_Value")
            .ret()
            ;
        }
Example #7
0
        private void BuildCloneValueMethod(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType
            )
        {
            var methodType = mi.DeclaringType;
            var getMethod  = null as MethodInfo;
            var setMethod  = null as MethodInfo;

            if (mi is PropertyInfo)
            {
                getMethod = ((PropertyInfo)mi).GetGetMethod();

                if (getMethod == null)
                {
                    if (_type != _originalType)
                    {
                        getMethod  = _type.GetMethod("get_" + mi.Name);
                        methodType = _type;
                    }

                    if (getMethod == null || !IsMethodAccessible(getMethod))
                    {
                        return;
                    }
                }

                setMethod = ((PropertyInfo)mi).GetSetMethod();

                if (setMethod == null)
                {
                    if (_type != _originalType)
                    {
                        setMethod  = _type.GetMethod("set_" + mi.Name);
                        methodType = _type;
                    }

                    if (setMethod == null || !IsMethodAccessible(setMethod))
                    {
                        return;
                    }
                }
            }

            var method = nestedType.DefineMethod(_memberAccessor.GetMethod("CloneValue", typeof(object), typeof(object)));
            var emit   = method.Emitter;

            emit
            .ldarg_2
            .castType(methodType)
            .ldarg_1
            .castType(methodType)
            .end();

            if (mi is FieldInfo)
            {
                emit.ldfld((FieldInfo)mi);
            }
            else
            {
                emit.callvirt(getMethod);
            }

            if (typeof(string) != memberType && TypeHelper.IsSameOrParent(typeof(ICloneable), memberType))
            {
                if (memberType.IsValueType)
                {
                    emit
                    .box(memberType)
                    .callvirt(typeof(ICloneable), "Clone")
                    .unbox_any(memberType)
                    ;
                }
                else
                {
                    var valueIsNull = emit.DefineLabel();

                    emit
                    .dup
                    .brfalse_s(valueIsNull)
                    .callvirt(typeof(ICloneable), "Clone")
                    .castclass(memberType)
                    .MarkLabel(valueIsNull)
                    ;
                }
            }

            if (mi is FieldInfo)
            {
                emit.stfld((FieldInfo)mi);
            }
            else
            {
                emit.callvirt(setMethod);
            }

            emit
            .ret()
            ;
        }
Example #8
0
        private void BuildGetter(MemberInfo mi, TypeBuilderHelper nestedType)
        {
            Type       methodType = mi.DeclaringType;
            MethodInfo getMethod  = null;

            if (mi is PropertyInfo)
            {
                getMethod = ((PropertyInfo)mi).GetGetMethod();

                if (getMethod == null)
                {
                    if (_type != _originalType)
                    {
                        getMethod  = _type.GetMethod("get_" + mi.Name);
                        methodType = _type;
                    }

                    if (getMethod == null || !IsMethodAccessible(getMethod))
                    {
                        return;
                    }
                }
            }

            MethodBuilderHelper method = nestedType.DefineMethod(
                _memberAccessor.GetMethod("GetValue", typeof(object)));

            EmitHelper emit = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .end();

            if (mi is FieldInfo)
            {
                FieldInfo fi = (FieldInfo)mi;

                emit
                .ldfld(fi)
                .boxIfValueType(fi.FieldType)
                ;
            }
            else
            {
                PropertyInfo pi = (PropertyInfo)mi;

                emit
                .callvirt(getMethod)
                .boxIfValueType(pi.PropertyType)
                ;
            }

            emit
            .ret()
            ;

            nestedType.DefineMethod(_memberAccessor.GetProperty("HasGetter").GetGetMethod()).Emitter
            .ldc_i4_1
            .ret()
            ;
        }
		private void BuildTypedGetterForNullable(
			MemberInfo        mi,
			TypeBuilderHelper nestedType,
			Type              memberType)
		{
			var methodType = mi.DeclaringType;
			var getMethod  = null as MethodInfo;

			if (mi is PropertyInfo)
			{
				getMethod = ((PropertyInfo)mi).GetGetMethod();

				if (getMethod == null)
				{
					if (_type != _originalType)
					{
						getMethod  = _type.GetMethod("get_" + mi.Name);
						methodType = _type;
					}

					if (getMethod == null || !IsMethodAccessible(getMethod))
						return;
				}
			}

			var setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType);
			var methodInfo = _memberAccessor.GetMethod("Get" + setterType.Name, typeof(object));

			if (methodInfo == null)
				return;

			var method       = nestedType.DefineMethod(methodInfo);
			var nullableType = typeof(Nullable<>).MakeGenericType(memberType);
			var emit         = method.Emitter;

			emit
				.ldarg_1
				.castType (methodType)
				.end();

			if (mi is FieldInfo)
			{
				emit.ldflda  ((FieldInfo)mi);
			}
			else
			{
				var locNullable = emit.DeclareLocal(nullableType);

				emit
					.callvirt (getMethod)
					.stloc    (locNullable)
					.ldloca   (locNullable)
					;
			}

			emit
				.call(nullableType, "get_Value")
				.ret()
				;
		}
Example #10
0
		private void BuildTypedGetter(
			MemberInfo        mi,
			TypeBuilderHelper nestedType,
			string            typedPropertyName)
		{
			var methodType = mi.DeclaringType;
			var getMethod  = null as MethodInfo;

			if (mi is PropertyInfo)
			{
				getMethod = ((PropertyInfo)mi).GetGetMethod();

				if (getMethod == null)
				{
					if (_type != _originalType)
					{
						getMethod  = _type.GetMethod("get_" + mi.Name);
						methodType = _type;
					}

					if (getMethod == null || !IsMethodAccessible(getMethod))
						return;
				}
			}

			var methodInfo = _memberAccessor.GetMethod("Get" + typedPropertyName, typeof(object));

			if (methodInfo == null)
				return;

			var method = nestedType.DefineMethod(methodInfo);
			var emit   = method.Emitter;

			emit
				.ldarg_1
				.castType (methodType)
				.end();

			if (mi is FieldInfo) emit.ldfld   ((FieldInfo)mi);
			else                 emit.callvirt(getMethod);

			emit
				.ret()
				;
		}
Example #11
0
		private void BuildSetter(MemberInfo mi, TypeBuilderHelper nestedType)
		{
			var methodType = mi.DeclaringType;
			var setMethod  = null as MethodInfo;

			if (mi is PropertyInfo)
			{
				setMethod = ((PropertyInfo)mi).GetSetMethod();

				if (setMethod == null)
				{
					if (_type != _originalType)
					{
						setMethod  = _type.GetMethod("set_" + mi.Name);
						methodType = _type;
					}

					if (setMethod == null || !IsMethodAccessible(setMethod))
						return;
				}
			}
			//else if (((FieldInfo)mi).IsLiteral)
			//	return;

			var method = nestedType.DefineMethod(_memberAccessor.GetMethod("SetValue", typeof(object), typeof(object)));
			var emit   = method.Emitter;

			emit
				.ldarg_1
				.castType (methodType)
				.ldarg_2
				.end();

			if (mi is FieldInfo)
			{
				var fi = (FieldInfo)mi;

				emit
					.CastFromObject (fi.FieldType)
					.stfld          (fi)
					;
			}
			else
			{
				var pi = (PropertyInfo)mi;

				emit
					.CastFromObject (pi.PropertyType)
					.callvirt       (setMethod)
					;
			}

			emit
				.ret()
				;

			nestedType.DefineMethod(_memberAccessor.GetProperty("HasSetter").GetGetMethod()).Emitter
				.ldc_i4_1
				.ret()
				;
		}
Example #12
0
        void BuildCreateInstanceMethods()
        {
            var isValueType  = _type.IsValueType;
            var baseDefCtor  = isValueType? null: _type.GetPublicDefaultConstructor();
            var baseInitCtor = _type.GetPublicConstructor(typeof(InitContext));

            if (baseDefCtor == null && baseInitCtor == null && !isValueType)
            {
                return;
            }

            // CreateInstance.
            //
            var method = _typeBuilder.DefineMethod(_accessorType.GetMethod(false, "CreateInstance", Type.EmptyTypes));

            if (baseDefCtor != null)
            {
                method.Emitter
                .newobj(baseDefCtor)
                .ret()
                ;
            }
            else if (isValueType)
            {
                var locObj = method.Emitter.DeclareLocal(_type);

                method.Emitter
                .ldloca(locObj)
                .initobj(_type)
                .ldloc(locObj)
                .box(_type)
                .ret()
                ;
            }
            else
            {
                method.Emitter
                .ldnull
                .newobj(baseInitCtor)
                .ret()
                ;
            }

            // CreateInstance(IniContext).
            //
            method = _typeBuilder.DefineMethod(
                _accessorType.GetMethod(false, "CreateInstance", typeof(InitContext)));

            if (baseInitCtor != null)
            {
                method.Emitter
                .ldarg_1
                .newobj(baseInitCtor)
                .ret()
                ;
            }
            else if (isValueType)
            {
                var locObj = method.Emitter.DeclareLocal(_type);

                method.Emitter
                .ldloca(locObj)
                .initobj(_type)
                .ldloc(locObj)
                .box(_type)
                .ret()
                ;
            }
            else
            {
                method.Emitter
                .newobj(baseDefCtor)
                .ret()
                ;
            }
        }
Example #13
0
        private bool BuildMembers(Type interfaceType)
        {
            FieldInfo    objectsField = typeof(DuckType).GetField("_objects", BindingFlags.NonPublic | BindingFlags.Instance);
            BindingFlags flags        = BindingFlags.Public | BindingFlags.Instance
                                        | (DuckTyping.AllowStaticMembers? BindingFlags.Static | BindingFlags.FlattenHierarchy: 0);

            foreach (MethodInfo interfaceMethod in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                MethodInfo targetMethod = null;
                int        typeIndex    = 0;

                for (; typeIndex < _objectTypes.Length; typeIndex++)
                {
                    if (_objectTypes[typeIndex] == null)
                    {
                        continue;
                    }

                    foreach (MethodInfo mi in _objectTypes[typeIndex].GetMethods(flags))
                    {
                        if (CompareMethodSignature(interfaceMethod, mi))
                        {
                            targetMethod = mi;
                            break;
                        }
                    }

                    if (targetMethod == null)
                    {
                        foreach (Type intf in _objectTypes[typeIndex].GetInterfaces())
                        {
                            if (intf.IsPublic || intf.IsNestedPublic)
                            {
                                foreach (MethodInfo mi in intf.GetMethods(flags))
                                {
                                    if (CompareMethodSignature(interfaceMethod, mi))
                                    {
                                        targetMethod = mi;
                                        break;
                                    }
                                }

                                if (targetMethod != null)
                                {
                                    break;
                                }
                            }
                        }
                    }

                    if (targetMethod != null)
                    {
                        break;
                    }
                }

                ParameterInfo[]     ips     = interfaceMethod.GetParameters();
                MethodBuilderHelper builder = _typeBuilder.DefineMethod(interfaceMethod);
                EmitHelper          emit    = builder.Emitter;

                if (targetMethod != null)
                {
                    Type targetType = targetMethod.DeclaringType;

                    if (!targetMethod.IsStatic)
                    {
                        emit
                        .ldarg_0
                        .ldfld(objectsField)
                        .ldc_i4(typeIndex)
                        .ldelem_ref
                        .end()
                        ;

                        if (targetType.IsValueType)
                        {
                            // For value types we have to use stack.
                            //
                            LocalBuilder obj = emit.DeclareLocal(targetType);

                            emit
                            .unbox_any(targetType)
                            .stloc(obj)
                            .ldloca(obj)
                            ;
                        }
                        else
                        {
                            emit
                            .castclass(targetType)
                            ;
                        }
                    }

                    foreach (ParameterInfo p in ips)
                    {
                        emit.ldarg(p);
                    }

                    if (targetMethod.IsStatic || targetMethod.IsFinal || targetMethod.DeclaringType.IsSealed)
                    {
                        emit
                        .call(targetMethod)
                        .ret();
                    }
                    else
                    {
                        emit
                        .callvirt(targetMethod)
                        .ret();
                    }
                }
                else
                {
                    // Method or property was not found.
                    // Insert an empty stub or stub that throws the NotImplementedException.
                    //
                    MustImplementAttribute attr = (MustImplementAttribute)
                                                  Attribute.GetCustomAttribute(interfaceMethod, typeof(MustImplementAttribute));

                    if (attr == null)
                    {
                        attr = (MustImplementAttribute)Attribute.GetCustomAttribute(
                            interfaceMethod.DeclaringType, typeof(MustImplementAttribute));
                        if (attr == null)
                        {
                            attr = _defaultAttribute;
                        }
                    }

                    // When the member is marked as 'Required' throw a build-time exception.
                    //
                    if (attr.Implement)
                    {
                        if (attr.ThrowException)
                        {
                            throw new TypeBuilderException(string.Format(
                                                               Resources.TypeBuilder_PublicMethodMustBeImplemented,
                                                               _objectTypes.Length > 0 && _objectTypes[0] != null ? _objectTypes[0].FullName : "???",
                                                               interfaceMethod));
                        }
                        else
                        {
                            // Implement == true, but ThrowException == false.
                            // In this case the null pointer will be returned.
                            // This mimics the 'as' operator behaviour.
                            //
                            return(false);
                        }
                    }

                    if (attr.ThrowException)
                    {
                        string message = attr.ExceptionMessage;

                        if (message == null)
                        {
                            message = string.Format(Resources.TypeBuilder_PublicMethodNotImplemented,
                                                    _objectTypes.Length > 0 && _objectTypes[0] != null ? _objectTypes[0].FullName : "???",
                                                    interfaceMethod);
                        }

                        emit
                        .ldstr(message)
                        .newobj(typeof(NotImplementedException), typeof(string))
                        .@throw
                        .end();
                    }
                    else
                    {
                        // Emit a 'do nothing' stub.
                        //
                        LocalBuilder returnValue = null;

                        if (interfaceMethod.ReturnType != typeof(void))
                        {
                            returnValue = emit.DeclareLocal(interfaceMethod.ReturnType);
                            emit.Init(returnValue);
                        }

                        // Initialize out parameters.
                        //
                        ParameterInfo[] parameters = ips;

                        if (parameters != null)
                        {
                            emit.InitOutParameters(parameters);
                        }

                        if (returnValue != null)
                        {
                            emit.ldloc(returnValue);
                        }

                        emit.ret();
                    }
                }
            }

            return(true);
        }
        private void CreateUpdateFunction(Type type, TypeBuilderHelper typeBuilderHelper)
        {
            var classMetadata       = ClassMetaDataManager.Instace.GetClassMetaData(type);
            var properties          = classMetadata.Properties;
            var mappingTable        = classMetadata.MappingTable;
            var methodEmit          = typeBuilderHelper.DefineMethod(typeof(IDbFunctionHelper).GetMethod("Update")).Emitter;
            var resultLocal         = methodEmit.DeclareLocal(typeof(int));
            var commandLocal        = methodEmit.DeclareLocal(typeof(DbCommand));
            var commandParameters   = methodEmit.DeclareLocal(typeof(DbParameterCollection));
            var queryBuilder        = new StringBuilder("UPDATE " + mappingTable + " SET ");
            var objectNotDirtyLabel = methodEmit.DefineLabel();

            foreach (var mappingInfo in properties.Values)
            {
                if (mappingInfo.MappingField != "Id")
                {
                    queryBuilder.Append(mappingInfo.MappingField + "=@" + mappingInfo.MappingField + ", ");
                }
            }
            var tmpString = queryBuilder.ToString(0, queryBuilder.Length - 2);

            queryBuilder.Length = 0;
            queryBuilder.Append(tmpString);
            queryBuilder.Append(" WHERE Id = @Id");
            methodEmit
            .ldarg_1
            .call(typeof(IDbObject).GetMethod("get_IsDirty"))
            .brfalse(objectNotDirtyLabel)
            .ldc_i4_0
            .stloc(resultLocal)
            .ldarg_2
            .call(typeof(DbConnection).GetMethod("CreateCommand"))
            .stloc(commandLocal)
            .ldloc(commandLocal)
            .ldstr(queryBuilder.ToString())
            .call(typeof(DbCommand).GetMethod("set_CommandText"))
            .ldloc(commandLocal)
            .call(typeof(DbCommand).GetMethod("get_Parameters"))
            .stloc(commandParameters);
            foreach (var mappingInfo in properties.Values)
            {
                var propertyInfo = mappingInfo.PropertyInfo;
                var mappingField = mappingInfo.MappingField;
                var propertyType = propertyInfo.PropertyType;
                if (propertyType.IsPrimitive || propertyType == typeof(string) || propertyType == typeof(DateTime) || propertyType == typeof(decimal))
                {
                    methodEmit
                    .ldloc(commandParameters)
                    .ldstr("@" + mappingField)                                      //Param 1 for MySqlParameter constructor
                    .ldarg_1
                    .call(propertyInfo.GetGetMethod())                              //Param 2 for MySqlParameter constructor
                    .newobj(typeof(MySqlParameter), typeof(string), typeof(object)) // Param for Add of DbParameterCollection
                    .call(typeof(DbParameterCollection).GetMethod("Add", new[] { typeof(object) }))
                    ;
                }
                else                 //Property that need to be convert to byte array before set
                {
                    var propetyValueLocal       = methodEmit.DeclareLocal(propertyType);
                    var dbSerializerHelperLocal = methodEmit.DeclareLocal(typeof(DbSerializerHelper));
                    var memoryStreamLocal       = methodEmit.DeclareLocal(typeof(MemoryStream));
                    var propertyByteArray       = methodEmit.DeclareLocal(typeof(byte[]));
                    methodEmit
                    .ldarg_1
                    .call(propertyInfo.GetGetMethod())
                    .stloc(propetyValueLocal)
                    .newobj(typeof(MemoryStream), Type.EmptyTypes)
                    .stloc(memoryStreamLocal);
                    methodEmit.BeginExceptionBlock();
                    methodEmit
                    .ldloc(memoryStreamLocal)
                    .newobj(typeof(BinaryWriter), typeof(Stream))
                    .newobj(typeof(DbSerializerHelper), typeof(BinaryWriter))
                    .stloc(dbSerializerHelperLocal)
                    .ldloc(dbSerializerHelperLocal)
                    .ldarg_1
                    .call(propertyInfo.GetGetMethod())
                    .call(typeof(DbSerializerHelper).GetMethod("Write", new[] { propertyType }))
                    .ldloc(memoryStreamLocal)
                    .call(typeof(MemoryStream).GetMethod("ToArray"))
                    .stloc(propertyByteArray)
                    .ldloc(commandParameters)
                    .ldstr("@" + mappingField)
                    .ldloc(propertyByteArray)
                    .newobj(typeof(MySqlParameter), typeof(string), typeof(object))                             // Param for Add of DbParameterCollection
                    .call(typeof(DbParameterCollection).GetMethod("Add", new[] { typeof(object) }))
                    .BeginFinallyBlock()
                    .ldloc(memoryStreamLocal)
                    .call(typeof(IDisposable).GetMethod("Dispose"))
                    .EndExceptionBlock()
                    ;
                }
            }

            methodEmit
            .ldloc(commandLocal)
            .call(typeof(DbCommand).GetMethod("ExecuteNonQuery"))
            .stloc(resultLocal)
            .ldarg_1
            .ldc_bool(false)
            .call(typeof(IDbObject).GetMethod("set_IsDirty"))
            .MarkLabel(objectNotDirtyLabel);

            //Update relation
            var          relations          = classMetadata.RelationProperties;
            LocalBuilder queryExecutorLocal = null;

            if (relations.Count > 0)
            {
                queryExecutorLocal = methodEmit.DeclareLocal(typeof(IQueryExecutor));
                var dbObjectContainerField = typeBuilderHelper.TypeBuilder.GetField("dbObjectContainer");
                methodEmit
                .ldfld(dbObjectContainerField)
                .call(typeof(DbObjectContainer).GetMethod("get_QueryExecutor"))
                .stloc(queryExecutorLocal);
            }
            foreach (var relationInfo in relations.Values)
            {
                var propertyInfo = relationInfo.PropertyInfo;
                var propertyType = propertyInfo.PropertyType;
                var elementType  = propertyType.IsGenericType ? propertyType.GetGenericArguments()[0] : propertyType;
                var listPersistentDbObjectLocal = methodEmit.DeclareLocal(typeof(IList <long>));
                var listCurrentType             = typeof(List <>).MakeGenericType(elementType);
                var addElementMethod            = typeof(ICollection <>).MakeGenericType(elementType).GetMethod("Add");
                var countElementMethod          = typeof(ICollection <>).MakeGenericType(elementType).GetMethod("Count");
                var listConstructorMethod       =
                    listCurrentType.GetConstructor(new[] { typeof(IEnumerable <>).MakeGenericType(elementType) });
                var listCurrentDbObjectLocal = methodEmit.DeclareLocal(listCurrentType);
                var mappingColumn            = relationInfo.PartnerKey;
                var relationCommandLocal     = methodEmit.DeclareLocal(typeof(DbCommand));
                var readerLocal           = methodEmit.DeclareLocal(typeof(DbDataReader));
                var relationTimeInfoLocal = methodEmit.DeclareLocal(typeof(TimeRelationInfo));
                var commandText           = "SELECT " + mappingColumn + " FROM " + mappingTable + " WHERE Id = @Id";
                methodEmit
                .ldarg_2
                .call(typeof(DbConnection).GetMethod("CreateCommand"))
                .stloc(relationCommandLocal)
                .ldloc(relationCommandLocal)
                .ldstr(commandText)
                .call(typeof(DbCommand).GetMethod("set_CommandText"))
                .ldloc(relationCommandLocal)
                .call(typeof(DbCommand).GetMethod("ExecuteReader"))
                .stloc(readerLocal)
                .ldstr(mappingColumn)
                .ldloc(readerLocal)
                .call(typeof(DbSerializerHelper).GetMethod("ReadRelationTimeInfo"))
                .stloc(relationTimeInfoLocal)
                .ldloc(relationTimeInfoLocal)
                .ldfld(typeof(TimeRelationInfo).GetField("idList"))
                .stloc(listPersistentDbObjectLocal)
                ;
                if (relationInfo.RelationKind == RelationInfo.RELATION_1_1)
                {
                    methodEmit
                    .newobj(listCurrentType, Type.EmptyTypes)
                    .stloc(listCurrentDbObjectLocal)
                    .ldloc(listCurrentDbObjectLocal)
                    .ldarg_1
                    .call(propertyInfo.GetGetMethod())
                    .call(addElementMethod)
                    ;
                }
                else
                {
                    methodEmit
                    .ldarg_1
                    .call(propertyInfo.GetGetMethod())
                    .newobj(listConstructorMethod)
                    .stloc(listCurrentDbObjectLocal)
                    ;
                }

                var lenLocal                                    = methodEmit.DeclareLocal(typeof(int));
                var iLocal                                      = methodEmit.DeclareLocal(typeof(int));
                var beginForLabel                               = methodEmit.DefineLabel();
                var beginForBodyLabel                           = methodEmit.DefineLabel();
                var itemLocal                                   = methodEmit.DeclareLocal(elementType);
                var itemIdLocal                                 = methodEmit.DeclareLocal(typeof(long));
                var itemNullLabel                               = methodEmit.DefineLabel();
                var getCurrentObjectElementMethod               = listCurrentType.GetMethod("get_Item", new[] { typeof(int) });
                var listPersistentContainCurrentElementLabel    = methodEmit.DefineLabel();
                var listPersistentNotContainCurrentElementLabel = methodEmit.DefineLabel();

                methodEmit
                .ldloc(listCurrentDbObjectLocal)
                .call(countElementMethod)
                .stloc(lenLocal)
                .ldc_i4_0
                .stloc(iLocal)
                .br(beginForLabel)
                .MarkLabel(beginForBodyLabel)
                .ldloc(listCurrentDbObjectLocal)
                .ldloc(iLocal)
                .call(getCurrentObjectElementMethod)
                .stloc(itemLocal)
                .ldloc(itemLocal)
                .brfalse(itemNullLabel)
                .ldloc(itemLocal)
                .call(typeof(IDbObject).GetMethod("get_Id"))
                .stloc(itemIdLocal)
                .ldloc(listPersistentDbObjectLocal)
                .ldloc(itemIdLocal)
                .call(typeof(ICollection <long>).GetMethod("Contain"))
                .brtrue(listPersistentContainCurrentElementLabel)

                .ldloc(queryExecutorLocal)
                .ldloc(itemLocal)
                .ldnull

                .call(typeof(IQueryExecutor).GetMethod("Insert", new[] { typeof(IDbObject), typeof(IsolationLevel?), typeof(long), typeof(string) }))

                .br(listPersistentNotContainCurrentElementLabel)
                .MarkLabel(listPersistentContainCurrentElementLabel)

                .MarkLabel(listPersistentNotContainCurrentElementLabel)
                .MarkLabel(itemNullLabel)
                .ldloc(iLocal)
                .ldc_i4_1
                .add
                .stloc(iLocal)
                .MarkLabel(beginForLabel)
                .ldloc(iLocal)
                .ldloc(lenLocal)
                .blt(beginForBodyLabel)
                ;
            }
        }
Example #15
0
        private static Type EnsureDelegateType(BuildContext context, MethodInfo method)
        {
            // The delegate should be defined as inner type of context.TypeBuilder.
            // It's possible, but we can not define and use newly defined type as Emit target in its owner type.
            // To solve this problem, we should create a top level delegate and make sure its name is unique.
            //
            string delegateName = context.TypeBuilder.TypeBuilder.FullName + "$" + method.Name + "$Delegate";
            Type   delegateType = (Type)context.Items[delegateName];

            if (delegateType == null)
            {
                ParameterInfo[] pi         = method.GetParameters();
                Type[]          parameters = new Type[pi.Length];

                for (int i = 0; i < pi.Length; i++)
                {
                    parameters[i] = pi[i].ParameterType;
                }

                const MethodImplAttributes mia = MethodImplAttributes.Runtime | MethodImplAttributes.Managed;
                const MethodAttributes     ma  = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;

                TypeBuilderHelper delegateBuilder = context.AssemblyBuilder.DefineType(delegateName,
                                                                                       TypeAttributes.Class | TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass,
                                                                                       typeof(MulticastDelegate));

                // Create constructor
                //
                ConstructorBuilderHelper ctorBuilder = delegateBuilder.DefineConstructor(
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, CallingConventions.Standard,
                    typeof(object), typeof(IntPtr));
                ctorBuilder.ConstructorBuilder.SetImplementationFlags(mia);

                MethodBuilderHelper methodBuilder;

                // Define the BeginInvoke method for the delegate
                //
                Type[] beginParameters = new Type[parameters.Length + 2];

                Array.Copy(parameters, 0, beginParameters, 0, parameters.Length);
                beginParameters[parameters.Length]     = typeof(AsyncCallback);
                beginParameters[parameters.Length + 1] = typeof(object);

                methodBuilder = delegateBuilder.DefineMethod("BeginInvoke", ma, typeof(IAsyncResult), beginParameters);
                methodBuilder.MethodBuilder.SetImplementationFlags(mia);

                // Define the EndInvoke method for the delegate
                //
                methodBuilder = delegateBuilder.DefineMethod("EndInvoke", ma, method.ReturnType, typeof(IAsyncResult));
                methodBuilder.MethodBuilder.SetImplementationFlags(mia);

                // Define the Invoke method for the delegate
                //
                methodBuilder = delegateBuilder.DefineMethod("Invoke", ma, method.ReturnType, parameters);
                methodBuilder.MethodBuilder.SetImplementationFlags(mia);

                context.Items[delegateName] = delegateType = delegateBuilder.Create();
            }

            return(delegateType);
        }
Example #16
0
		private void BuildGetter(MemberInfo mi, TypeBuilderHelper nestedType)
		{
			var methodType = mi.DeclaringType;
			var getMethod  = null as MethodInfo;

			if (mi is PropertyInfo)
			{
				getMethod = ((PropertyInfo)mi).GetGetMethod();

				if (getMethod == null)
				{
					if (_type != _originalType)
					{
						getMethod  = _type.GetMethod("get_" + mi.Name);
						methodType = _type;
					}

					if (getMethod == null || !IsMethodAccessible(getMethod))
						return;
				}
			}

			var method = nestedType.DefineMethod(_memberAccessor.GetMethod("GetValue", typeof(object)));
			var emit   = method.Emitter;

			emit
				.ldarg_1
				.castType (methodType)
				.end();

			if (mi is FieldInfo)
			{
				var fi = (FieldInfo)mi;

				emit
					.ldfld          (fi)
					.boxIfValueType (fi.FieldType)
					;
			}
			else
			{
				if (methodType.IsValueType)
				{
					var loc = emit.DeclareLocal(methodType);

					emit
						.stloc      ((byte)loc.LocalIndex)
						.ldloca_s   ((byte)loc.LocalIndex);
				}

				var pi = (PropertyInfo)mi;

				emit
					.callvirt       (getMethod)
					.boxIfValueType (pi.PropertyType)
					;
			}

			emit
				.ret()
				;

			nestedType.DefineMethod(_memberAccessor.GetProperty("HasGetter").GetGetMethod()).Emitter
				.ldc_i4_1
				.ret()
				;
		}
Example #17
0
        private void BuildGetter(MemberInfo mi, TypeBuilderHelper nestedType)
        {
            var methodType = mi.DeclaringType;
            var getMethod  = null as MethodInfo;

            if (mi is PropertyInfo)
            {
                getMethod = ((PropertyInfo)mi).GetGetMethod();

                if (getMethod == null)
                {
                    if (_type != _originalType)
                    {
                        getMethod  = _type.GetMethod("get_" + mi.Name);
                        methodType = _type;
                    }

                    if (getMethod == null || !IsMethodAccessible(getMethod))
                    {
                        return;
                    }
                }
            }

            var method = nestedType.DefineMethod(_memberAccessor.GetMethod("GetValue", typeof(object)));
            var emit   = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .end();

            if (mi is FieldInfo)
            {
                var fi = (FieldInfo)mi;

                emit
                .ldfld(fi)
                .boxIfValueType(fi.FieldType)
                ;
            }
            else
            {
                if (methodType.IsValueType)
                {
                    var loc = emit.DeclareLocal(methodType);

                    emit
                    .stloc((byte)loc.LocalIndex)
                    .ldloca_s((byte)loc.LocalIndex);
                }

                var pi = (PropertyInfo)mi;

                emit
                .callvirt(getMethod)
                .boxIfValueType(pi.PropertyType)
                ;
            }

            emit
            .ret()
            ;

            nestedType.DefineMethod(_memberAccessor.GetProperty("HasGetter").GetGetMethod()).Emitter
            .ldc_i4_1
            .ret()
            ;
        }
Example #18
0
		private void BuildIsNull(
			MemberInfo        mi,
			TypeBuilderHelper nestedType,
			Type              memberType)
		{
			var methodType = mi.DeclaringType;
			var getMethod  = null as MethodInfo;
			var isNullable = TypeHelper.IsNullable(memberType);
			var isValueType = (!isNullable && memberType.IsValueType);

			if (!isValueType && mi is PropertyInfo)
			{
				getMethod = ((PropertyInfo)mi).GetGetMethod();

				if (getMethod == null)
				{
					if (_type != _originalType)
					{
						getMethod  = _type.GetMethod("get_" + mi.Name);
						methodType = _type;
					}

					if (getMethod == null)
						return;
				}
			}

			var methodInfo = _memberAccessor.GetMethod("IsNull");

			if (methodInfo == null)
				return;

			var method = nestedType.DefineMethod(methodInfo);
			var emit   = method.Emitter;

			if (isValueType)
			{
				emit
					.ldc_i4_0
					.end()
					;
			}
			else
			{
				LocalBuilder locObj = null;

				if (isNullable)
					locObj = method.Emitter.DeclareLocal(memberType);

				emit
					.ldarg_1
					.castType (methodType)
					.end();

				if (mi is FieldInfo) emit.ldfld   ((FieldInfo)mi);
				else                 emit.callvirt(getMethod);

				if (isNullable)
				{
					emit
						.stloc(locObj)
						.ldloca(locObj)
						.call(memberType, "get_HasValue")
						.ldc_i4_0
						.ceq
						.end();
				}
				else
				{
					emit
						.ldnull
						.ceq
						.end();
				}
			}

			emit
				.ret()
				;
		}
Example #19
0
        private void BuildSetter(MemberInfo mi, TypeBuilderHelper nestedType)
        {
            var methodType = mi.DeclaringType;
            var setMethod  = null as MethodInfo;

            if (mi is PropertyInfo)
            {
                setMethod = ((PropertyInfo)mi).GetSetMethod();

                if (setMethod == null)
                {
                    if (_type != _originalType)
                    {
                        setMethod  = _type.GetMethod("set_" + mi.Name);
                        methodType = _type;
                    }

                    if (setMethod == null || !IsMethodAccessible(setMethod))
                    {
                        return;
                    }
                }
            }
            //else if (((FieldInfo)mi).IsLiteral)
            //	return;

            var method = nestedType.DefineMethod(_memberAccessor.GetMethod("SetValue", typeof(object), typeof(object)));
            var emit   = method.Emitter;

            emit
            .ldarg_1
            .castType(methodType)
            .ldarg_2
            .end();

            if (mi is FieldInfo)
            {
                var fi = (FieldInfo)mi;

                emit
                .CastFromObject(fi.FieldType)
                .stfld(fi)
                ;
            }
            else
            {
                var pi = (PropertyInfo)mi;

                emit
                .CastFromObject(pi.PropertyType)
                .callvirt(setMethod)
                ;
            }

            emit
            .ret()
            ;

            nestedType.DefineMethod(_memberAccessor.GetProperty("HasSetter").GetGetMethod()).Emitter
            .ldc_i4_1
            .ret()
            ;
        }
Example #20
0
		private void BuildCloneValueMethod(
			MemberInfo        mi,
			TypeBuilderHelper nestedType,
			Type              memberType
			)
		{
			var methodType = mi.DeclaringType;
			var getMethod  = null as MethodInfo;
			var setMethod  = null as MethodInfo;

			if (mi is PropertyInfo)
			{
				getMethod = ((PropertyInfo)mi).GetGetMethod();

				if (getMethod == null)
				{
					if (_type != _originalType)
					{
						getMethod  = _type.GetMethod("get_" + mi.Name);
						methodType = _type;
					}

					if (getMethod == null || !IsMethodAccessible(getMethod))
						return;
				}

				setMethod = ((PropertyInfo)mi).GetSetMethod();

				if (setMethod == null)
				{
					if (_type != _originalType)
					{
						setMethod  = _type.GetMethod("set_" + mi.Name);
						methodType = _type;
					}

					if (setMethod == null || !IsMethodAccessible(setMethod))
						return;
				}
			}

			var method = nestedType.DefineMethod(_memberAccessor.GetMethod("CloneValue", typeof(object), typeof(object)));
			var emit   = method.Emitter;

			emit
				.ldarg_2
				.castType (methodType)
				.ldarg_1
				.castType (methodType)
				.end();

			if (mi is FieldInfo)
				emit.ldfld   ((FieldInfo)mi);
			else
				emit.callvirt(getMethod);

			if (typeof(string) != memberType && TypeHelper.IsSameOrParent(typeof(ICloneable), memberType))
			{
				if (memberType.IsValueType)
					emit
						.box       (memberType)
						.callvirt  (typeof(ICloneable), "Clone")
						.unbox_any (memberType)
						;
				else
				{
					var valueIsNull = emit.DefineLabel();

					emit
						.dup
						.brfalse_s (valueIsNull)
						.callvirt  (typeof(ICloneable), "Clone")
						.castclass (memberType)
						.MarkLabel (valueIsNull)
						;
				}
			}

			if (mi is FieldInfo)
				emit.stfld   ((FieldInfo)mi);
			else
				emit.callvirt(setMethod);

			emit
				.ret()
				;
		}
Example #21
0
        private void BuildIsNull(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType)
        {
            var methodType  = mi.DeclaringType;
            var getMethod   = null as MethodInfo;
            var isNullable  = TypeHelper.IsNullable(memberType);
            var isValueType = (!isNullable && memberType.IsValueType);

            if (!isValueType && mi is PropertyInfo)
            {
                getMethod = ((PropertyInfo)mi).GetGetMethod();

                if (getMethod == null)
                {
                    if (_type != _originalType)
                    {
                        getMethod  = _type.GetMethod("get_" + mi.Name);
                        methodType = _type;
                    }

                    if (getMethod == null)
                    {
                        return;
                    }
                }
            }

            var methodInfo = _memberAccessor.GetMethod("IsNull");

            if (methodInfo == null)
            {
                return;
            }

            var method = nestedType.DefineMethod(methodInfo);
            var emit   = method.Emitter;

            if (isValueType)
            {
                emit
                .ldc_i4_0
                .end()
                ;
            }
            else
            {
                LocalBuilder locObj = null;

                if (isNullable)
                {
                    locObj = method.Emitter.DeclareLocal(memberType);
                }

                emit
                .ldarg_1
                .castType(methodType)
                .end();

                if (mi is FieldInfo)
                {
                    emit.ldfld((FieldInfo)mi);
                }
                else
                {
                    emit.callvirt(getMethod);
                }

                if (isNullable)
                {
                    emit
                    .stloc(locObj)
                    .ldloca(locObj)
                    .call(memberType, "get_HasValue")
                    .ldc_i4_0
                    .ceq
                    .end();
                }
                else
                {
                    emit
                    .ldnull
                    .ceq
                    .end();
                }
            }

            emit
            .ret()
            ;
        }
Example #22
0
		private void BuildTypedSetterForNullable(
			MemberInfo        mi,
			TypeBuilderHelper nestedType,
			Type              memberType)
		{
			var methodType = mi.DeclaringType;
			var setMethod  = null as MethodInfo;

			if (mi is PropertyInfo)
			{
				setMethod = ((PropertyInfo)mi).GetSetMethod();

				if (setMethod == null)
				{
					if (_type != _originalType)
					{
						setMethod  = _type.GetMethod("set_" + mi.Name);
						methodType = _type;
					}

					if (setMethod == null || !IsMethodAccessible(setMethod))
						return;
				}
			}

			var setterType = (memberType.IsEnum ? Enum.GetUnderlyingType(memberType) : memberType);
			var methodInfo = _memberAccessor.GetMethod("Set" + setterType.Name, typeof(object), setterType);

			if (methodInfo == null)
				return;

			var method = nestedType.DefineMethod(methodInfo);
			var emit   = method.Emitter;

			emit
				.ldarg_1
				.castType (methodType)
				.ldarg_2
				.newobj   (typeof(Nullable<>).MakeGenericType(memberType), memberType)
				.end();

			if (mi is FieldInfo) emit.stfld   ((FieldInfo)mi);
			else                 emit.callvirt(setMethod);

			emit
				.ret()
				;
		}
Example #23
0
        private bool BuildMembers(Type interfaceType)
        {
            FieldInfo    objectField = typeof(DuckType).GetField("_object", BindingFlags.NonPublic | BindingFlags.Instance);
            BindingFlags flags       = BindingFlags.Public | BindingFlags.Instance
                                       | (DuckTyping.AllowStaticMembers? BindingFlags.Static | BindingFlags.FlattenHierarchy: 0);

            foreach (MethodInfo interfaceMethod in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                ParameterInfo[] ips          = interfaceMethod.GetParameters();
                MethodInfo      targetMethod = null;

                foreach (MethodInfo mi in _objectType.GetMethods(flags))
                {
                    ParameterInfo[] ops = mi.GetParameters();

                    if (mi.Name == interfaceMethod.Name &&
                        mi.ReturnType == interfaceMethod.ReturnType &&
                        ops.Length == ips.Length)
                    {
                        targetMethod = mi;

                        for (int i = 0; i < ips.Length && targetMethod != null; i++)
                        {
                            ParameterInfo ip = ips[i];
                            ParameterInfo op = ops[i];

                            if (ip.ParameterType != op.ParameterType ||
                                ip.IsIn != op.IsIn ||
                                ip.IsOut != op.IsOut)
                            {
                                targetMethod = null;
                            }
                        }

                        if (targetMethod != null)
                        {
                            break;
                        }
                    }
                }

                MethodBuilderHelper builder = _typeBuilder.DefineMethod(interfaceMethod);
                EmitHelper          emit    = builder.Emitter;

                if (targetMethod != null)
                {
                    if (!targetMethod.IsStatic)
                    {
                        emit
                        .ldarg_0
                        .ldfld(objectField)
                        ;

                        if (_objectType.IsValueType)
                        {
                            // For value types we have to use stack.
                            //
                            LocalBuilder obj = emit.DeclareLocal(_objectType);

                            emit
                            .unbox_any(_objectType)
                            .stloc(obj)
                            .ldloca(obj)
                            ;
                        }
                        else
                        {
                            emit
                            .castclass(_objectType)
                            ;
                        }
                    }

                    foreach (ParameterInfo p in interfaceMethod.GetParameters())
                    {
                        emit.ldarg(p);
                    }

                    if (targetMethod.IsStatic)
                    {
                        emit
                        .call(targetMethod)
                        .ret();
                    }
                    else
                    {
                        emit
                        .callvirt(targetMethod)
                        .ret();
                    }
                }
                else
                {
                    // Method or property was not found.
                    // Insert an empty stub or stub that throws the NotImplementedException.
                    //
                    MustImplementAttribute attr = (MustImplementAttribute)
                                                  Attribute.GetCustomAttribute(interfaceMethod, typeof(MustImplementAttribute));

                    if (attr == null)
                    {
                        attr = (MustImplementAttribute)Attribute.GetCustomAttribute(
                            interfaceMethod.DeclaringType, typeof(MustImplementAttribute));
                        if (attr == null)
                        {
                            attr = MustImplementAttribute.Default;
                        }
                    }

                    // When the member is marked as 'Required' throw a build-time exception.
                    //
                    if (attr.Implement)
                    {
                        if (attr.ThrowException)
                        {
                            throw new TypeBuilderException(string.Format(
                                                               Resources.TypeBuilder_PublicMethodMustBeImplemented,
                                                               _objectType.FullName, interfaceMethod));
                        }
                        else
                        {
                            // Implement == true, but ThrowException == false.
                            // In this case the null pointer will be returned.
                            // This mimics the 'as' operator behaviour.
                            //
                            return(false);
                        }
                    }

                    if (attr.ThrowException)
                    {
                        string message = attr.ExceptionMessage;

                        if (message == null)
                        {
                            message = string.Format(Resources.TypeBuilder_PublicMethodNotImplemented,
                                                    _objectType.FullName, interfaceMethod);
                        }

                        emit
                        .ldstr(message)
                        .newobj(typeof(NotImplementedException), typeof(string))
                        .@throw
                        .end();
                    }
                    else
                    {
                        // Emit a 'do nothing' stub.
                        //
                        LocalBuilder returnValue = null;

                        if (interfaceMethod.ReturnType != typeof(void))
                        {
                            returnValue = emit.DeclareLocal(interfaceMethod.ReturnType);
                            emit.Init(returnValue);
                        }

                        // Initialize out parameters.
                        //
                        ParameterInfo[] parameters = interfaceMethod.GetParameters();

                        if (parameters != null)
                        {
                            emit.InitOutParameters(parameters);
                        }

                        if (returnValue != null)
                        {
                            emit.ldloc(returnValue);
                        }

                        emit.ret();
                    }
                }
            }

            return(true);
        }