Exemplo n.º 1
0
        /// <summary>
        /// 构建构造函数【用于代理类】,因为IoC注入和Proxy使用的方式是不同的,Proxy可能直接用数组去构造,而IoC只能一个一个去注入
        /// </summary>
        /// <param name="typeBuilder">类型构造</param>
        /// <param name="sourceTypeOrInterfaceType">代理(接口或类)类型</param>
        /// <param name="interceptors">拦截器集合</param>
        /// <param name="interceptorFieldBuilder">拦截器构建,被定义为List接口</param>
        protected override void DefineConstructor(TypeBuilder typeBuilder, Type sourceTypeOrInterfaceType, Type[] interceptors, FieldBuilder interceptorFieldBuilder)
        {
            /*构造函数*/
            var ctorParamters = new List <Type>(1)
            {
                typeof(IInterceptor[])
            };
            var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ctorParamters.ToArray());

            /*fix argument length*/
            ctorParamters.Insert(0, sourceTypeOrInterfaceType);
            var ctorIL = new MockEmitBuilder(ctorBuilder.GetILGenerator(), ctorBuilder.CallingConvention, typeof(void), ctorParamters.ToArray());

            ctorIL.LoadArgument(0);
            ctorIL.LoadConstant(2);
            ctorIL.NewObject(typeof(List <IInterceptor>).GetConstructor(new[] { typeof(int) }));
            ctorIL.StoreField(interceptorFieldBuilder);

            ctorIL.LoadArgument(0);
            ctorIL.LoadField(interceptorFieldBuilder);

            ctorIL.LoadArgument(1);
            ctorIL.Call(typeof(List <IInterceptor>).GetMethod("AddRange", new[] { typeof(IInterceptor[]) }));

            ctorIL.Return();
        }
Exemplo n.º 2
0
        /// <summary>
        /// 构建方法
        /// </summary>
        /// <param name="member"></param>
        /// <param name="members"></param>
        /// <param name="exists"></param>
        /// <param name="typeBuilder">类型构建</param>
        /// <param name="sourceTypeOrInterfaceType">假如是承继父类的,则callBase就能生效</param>
        /// <param name="buildInterface">构建接口</param>
        /// <param name="found"></param>
        private void BuildMethod(MemberInfo member, MemberInfo[] members, List <MemberInfo> exists, TypeBuilder typeBuilder, Type sourceTypeOrInterfaceType, bool @buildInterface, MockSetup found)
        {
            var method = member as MethodInfo;

            if (!@buildInterface && method.IsFinal)
            {
                return;
            }

            /*泛型方法和基本方法有什么不同*/
            var parameters     = method.GetParameters();
            var parameterTypes = new List <Type>(parameters.Length);
            var voidReturn     = method.ReturnType == typeof(void);

            foreach (var parameter in parameters)
            {
                parameterTypes.Add(parameter.ParameterType);
            }

            var attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName;

            if (!buildInterface)
            {
                attributes = MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig;
            }

            var methodBuilder = typeBuilder.DefineMethod(method.Name,
                                                         attributes,
                                                         method.CallingConvention,
                                                         method.ReturnType, parameterTypes.ToArray());

            /*fix argument length*/
            parameterTypes.Insert(0, sourceTypeOrInterfaceType);

            var il = new MockEmitBuilder(methodBuilder.GetILGenerator(), method.CallingConvention, method.ReturnType, parameterTypes.ToArray());

            if (found == null)
            {
                goto _notImpl;
            }

            goto _impl;

_notImpl:
            {
                if (voidReturn)
                {
                    /*out 参数*/
                    for (var i = 0; i < parameters.Length; i++)
                    {
                        if (parameters[i].IsOut)
                        {
                            il.LoadArgument((ushort)(i + 1));
                            var ele = parameters[i].ParameterType.GetElementType();
                            if (ele.IsValueType)
                            {
                                if (this.IsEnumType(ele) || this.IsNullableEnumType(ele))
                                {
                                    il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                    il.StoreIndirect(Enum.GetUnderlyingType(ele));
                                }
                                else
                                {
                                    il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                    il.StoreIndirect(ele);
                                }
                            }
                            else
                            {
                                il.LoadNull();
                                il.StoreIndirect(parameters[i].ParameterType);
                            }
                        }
                    }

                    il.Return();
                    return;
                }

                il.NewObject(typeof(NotImplementedException), Type.EmptyTypes);
                il.Throw();
                il.Return();
                return;
            };
_impl:
            {
                /*void*/
                if (voidReturn)
                {
                    if (found.MethodToCallType == MockSetup.MethodToCall.Exception || found.MethodToCallType == MockSetup.MethodToCall.Void)
                    {
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(method.Name, string.Format("the method {0}.{1} return type is void, but mock donot  provide action callback;", this.TargetType.Name, method.Name));
                    }
                }
                else
                {
                    /*返回结果类型不匹配*/
                    if (found.GetType() != typeof(MockSetup <,>).MakeGenericType(new[] { this.TargetType, method.ReturnType }))
                    {
                        goto _notImpl;
                    }
                }

                /*返回基类类型,如果当前是接口类型的,则抛出异常*/
                if (found.MethodIndex == 0)
                {
                    if (@buildInterface)
                    {
                        goto _notImpl;
                    }

                    //this
                    foreach (var m in this.GetMembers(sourceTypeOrInterfaceType))
                    {
                        if (m.MemberType == MemberTypes.Method)
                        {
                            var pm = m as MethodInfo;
                            var pp = pm.GetParameters();
                            if (pm.Name == found.Method.Name && pp.Length == found.Method.GetParameters().Length)
                            {
                                il.LoadArgument(0);
                                for (ushort i = 1; i < pp.Length + 1; i++)
                                {
                                    il.LoadArgument(i);
                                }

                                il.Call(pm);
                                il.Return();
                                return;
                            }
                        }
                    }

                    throw new ArgumentOutOfRangeException(method.Name, string.Format("the method {0}.{1} cannot been found;", this.TargetType.Name, method.Name));
                }

                /*用该值定位到执行的是哪个方法,因重载的原因,有15个方法以上,具体要看MockSetup<,>*/
                var idx = MockSetupInfoStore.Enqueue(found);

                /*抛出异常*/
                if (found.MethodIndex == -1)
                {
                    il.LoadArgument(0);
                    il.LoadConstant(idx);
                    if (voidReturn)
                    {
                        il.Call(typeof(MockSetupInfoStore).GetMethod("Call_ExceptionWithNoResult").MakeGenericMethod(new[] { this.TargetType }));
                    }
                    else
                    {
                        il.Call(typeof(MockSetupInfoStore).GetMethod("Call_ExceptionWithResult").MakeGenericMethod(new[] { this.TargetType, method.ReturnType }));
                    }
                    il.Return();
                    return;
                }

                var callMethodName = typeof(MockSetupInfoStore).GetMethod(string.Concat("Call_", found.MethodIndex.ToString()));
                var makeGenericMethodParameterTypes = new List <Type>(found.MethodIndex);
                makeGenericMethodParameterTypes.Add(this.TargetType);

                if (found.MethodIndex >= 10 && found.MethodIndex <= 25)
                {
                    /*没有参数的方法*/
                    if (found.MethodIndex == 10)
                    {
                        /*out 参数*/
                        for (var i = 0; i < parameters.Length; i++)
                        {
                            if (parameters[i].IsOut)
                            {
                                il.LoadArgument((ushort)(i + 1));
                                var ele = parameters[i].ParameterType.GetElementType();
                                if (ele.IsValueType)
                                {
                                    if (this.IsEnumType(ele) || this.IsNullableEnumType(ele))
                                    {
                                        il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                        il.StoreIndirect(Enum.GetUnderlyingType(ele));
                                    }
                                    else
                                    {
                                        il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                        il.StoreIndirect(ele);
                                    }
                                }
                                else
                                {
                                    il.LoadNull();
                                    il.StoreIndirect(parameters[i].ParameterType);
                                }
                            }
                        }

                        makeGenericMethodParameterTypes.Add(method.ReturnType);
                        il.LoadArgument(0);
                        il.LoadConstant(idx);
                        il.Call(callMethodName.MakeGenericMethod(makeGenericMethodParameterTypes.ToArray()));
                        il.Return();
                        return;
                    }

                    if (found.CallbackMethodParameters == null || found.CallbackMethodParameters.Length == 0)
                    {
                        throw new ArgumentOutOfRangeException(method.Name, string.Format("{0}.{1} method need {2} parameters,but mock provider 0 parameters", this.TargetType.Name, method.Name, parameterTypes.Count));
                    }

                    if (parameterTypes.Count != found.CallbackMethodParameters.Length)
                    {
                        throw new ArgumentException(string.Format("{0}.{1} method need {2} parameters,but the mock provide {3} parameters", this.TargetType.Name, method.Name, parameters.Length.ToString(), found.CallbackMethodParameters.Length.ToString()), method.Name);
                    }

                    for (var i = 1; i < found.CallbackMethodParameters.Length; i++)
                    {
                        if (parameterTypes[i] != found.CallbackMethodParameters[i].ParameterType)
                        {
                            throw new ArgumentException(string.Format("{0}.{1} method the {2} parameter type is {3},but the mock provide {4} type", this.TargetType.Name, method.Name, i.ToString(), parameterTypes[i].Name, found.CallbackMethodParameters[i].ParameterType.Name), method.Name);
                        }

                        makeGenericMethodParameterTypes.Add(found.CallbackMethodParameters[i].ParameterType);
                    }

                    makeGenericMethodParameterTypes.Add(method.ReturnType);

                    /*out 参数*/
                    for (var i = 0; i < parameters.Length; i++)
                    {
                        if (parameters[i].IsOut)
                        {
                            il.LoadArgument((ushort)(i + 1));
                            var ele = parameters[i].ParameterType.GetElementType();
                            if (ele.IsValueType)
                            {
                                if (this.IsEnumType(ele) || this.IsNullableEnumType(ele))
                                {
                                    il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                    il.StoreIndirect(Enum.GetUnderlyingType(ele));
                                }
                                else
                                {
                                    il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                    il.StoreIndirect(ele);
                                }
                            }
                            else
                            {
                                il.LoadNull();
                                il.StoreIndirect(parameters[i].ParameterType);
                            }
                        }
                    }

                    il.LoadArgument(0);
                    il.LoadConstant(idx);
                    for (ushort i = 1; i < makeGenericMethodParameterTypes.Count - 1; i++)
                    {
                        il.LoadArgument(i);
                    }

                    il.Call(callMethodName.MakeGenericMethod(makeGenericMethodParameterTypes.ToArray()));
                    il.Return();
                    return;
                }

                if (found.MethodIndex >= 30 && found.MethodIndex <= 45)
                {
                    /*没有参数的方法*/
                    if (found.MethodIndex == 30)
                    {
                        /*out 参数*/
                        for (var i = 0; i < parameters.Length; i++)
                        {
                            if (parameters[i].IsOut)
                            {
                                il.LoadArgument((ushort)(i + 1));
                                var ele = parameters[i].ParameterType.GetElementType();
                                if (ele.IsValueType)
                                {
                                    if (this.IsEnumType(ele) || this.IsNullableEnumType(ele))
                                    {
                                        il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                        il.StoreIndirect(Enum.GetUnderlyingType(ele));
                                    }
                                    else
                                    {
                                        il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                        il.StoreIndirect(ele);
                                    }
                                }
                                else
                                {
                                    il.LoadNull();
                                    il.StoreIndirect(parameters[i].ParameterType);
                                }
                            }
                        }

                        il.LoadArgument(0);
                        il.LoadConstant(idx);
                        il.Call(callMethodName.MakeGenericMethod(makeGenericMethodParameterTypes.ToArray()));
                        il.Return();
                        return;
                    }

                    if (parameterTypes.Count != found.CallbackMethodParameters.Length)
                    {
                        throw new ArgumentException(string.Format("{0}.{1} method need {2} parameters,but the mock provide {3} parameters", this.TargetType.Name, method.Name, parameters.Length.ToString(), found.CallbackMethodParameters.Length.ToString()), method.Name);
                    }

                    for (var i = 1; i < found.CallbackMethodParameters.Length; i++)
                    {
                        if (parameterTypes[i] != found.CallbackMethodParameters[i].ParameterType)
                        {
                            throw new ArgumentException(string.Format("{0}.{1} method the {2} parameter type is {3},but the mock provide {4} type", this.TargetType.Name, method.Name, i.ToString(), parameterTypes[i].Name, found.CallbackMethodParameters[i].ParameterType.Name), method.Name);
                        }

                        makeGenericMethodParameterTypes.Add(found.CallbackMethodParameters[i].ParameterType);
                    }

                    /*out 参数*/
                    for (var i = 0; i < parameters.Length; i++)
                    {
                        if (parameters[i].IsOut)
                        {
                            il.LoadArgument((ushort)(i + 1));
                            var ele = parameters[i].ParameterType.GetElementType();
                            if (ele.IsValueType)
                            {
                                if (this.IsEnumType(ele) || this.IsNullableEnumType(ele))
                                {
                                    il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                    il.StoreIndirect(Enum.GetUnderlyingType(ele));
                                }
                                else
                                {
                                    il.Call(typeof(MockSetupInfoStore).GetMethod("ReturnDefault").MakeGenericMethod(new[] { ele }));
                                    il.StoreIndirect(ele);
                                }
                            }
                            else
                            {
                                il.LoadNull();
                                il.StoreIndirect(parameters[i].ParameterType);
                            }
                        }
                    }

                    il.LoadArgument(0);
                    il.LoadConstant(idx);
                    for (ushort i = 1; i < makeGenericMethodParameterTypes.Count; i++)
                    {
                        il.LoadArgument(i);
                    }

                    il.Call(callMethodName.MakeGenericMethod(makeGenericMethodParameterTypes.ToArray()));
                    il.Return();
                    return;
                }
            };
        }
Exemplo n.º 3
0
        /// <summary>
        /// 构建事件
        /// </summary>
        /// <param name="member"></param>
        /// <param name="members"></param>
        /// <param name="exists"></param>
        /// <param name="typeBuilder">类型构建</param>
        /// <param name="sourceTypeOrInterfaceType">假如是承继父类的,则callBase就能生效</param>
        /// <param name="buildInterface">构建接口</param>
        protected virtual void BuildEvent(MemberInfo member, MemberInfo[] members, List <MemberInfo> exists, TypeBuilder typeBuilder, Type sourceTypeOrInterfaceType, bool @buildInterface)
        {
            var @event = member as EventInfo;

            exists.Add(@event);
            var        addName = string.Concat("add_", @event.Name);
            var        removeName = string.Concat("remove_", @event.Name);
            MethodInfo addMethod = null, removeMethod = null;

            foreach (var m in members)
            {
                if (m.MemberType == MemberTypes.Method)
                {
                    if (addName == m.Name)
                    {
                        addMethod = (MethodInfo)m;
                        exists.Add(m);
                        if (removeMethod != null)
                        {
                            break;
                        }
                    }
                    else if (removeName == m.Name)
                    {
                        removeMethod = (MethodInfo)m;
                        exists.Add(m);
                        if (addMethod != null)
                        {
                            break;
                        }
                    }
                }
            }

            FieldBuilder fieldBuilder = null;
            EventBuilder eventBuilder = null;

            if (!@buildInterface && (addMethod == null || addMethod.IsFinal) && (removeMethod == null || removeMethod.IsFinal))
            {
                return;
            }

            eventBuilder = typeBuilder.DefineEvent(@event.Name, @event.Attributes, @event.EventHandlerType);

            if (addMethod != null)
            {
                fieldBuilder = typeBuilder.DefineField(@event.Name, @event.EventHandlerType, FieldAttributes.Private);
                /*泛型方法和基本方法有什么不同*/
                var parameters     = addMethod.GetParameters();
                var parameterTypes = new List <Type>(parameters.Length);
                var voidReturn     = addMethod.ReturnType == typeof(void);

                foreach (var parameter in parameters)
                {
                    parameterTypes.Add(parameter.ParameterType);
                }

                var attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName;
                if (!buildInterface)
                {
                    attributes = MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig;
                }

                var methodBuilder = typeBuilder.DefineMethod(addMethod.Name,
                                                             attributes,
                                                             addMethod.CallingConvention,
                                                             addMethod.ReturnType, parameterTypes.ToArray());

                /*fix argument length*/
                parameterTypes.Insert(0, sourceTypeOrInterfaceType);
                var il     = new MockEmitBuilder(methodBuilder.GetILGenerator(), addMethod.CallingConvention, addMethod.ReturnType, parameterTypes.ToArray());
                var locals = new[]
                {
                    il.DeclareLocal(@event.EventHandlerType),
                    il.DeclareLocal(@event.EventHandlerType),
                    il.DeclareLocal(@event.EventHandlerType),
                };
                var label = il.DefineLabel();

                il.LoadArgument(0);
                il.LoadField(fieldBuilder);
                il.StoreLocal(locals[0]);

                il.MarkLabel(label);
                il.LoadLocal(locals[0]);
                il.StoreLocal(locals[1]);
                il.LoadLocal(locals[1]);
                il.LoadArgument(1);

                MethodInfo delegateMethod = null;
                foreach (var method in typeof(System.Delegate).GetMethods(BindingFlags.Public | BindingFlags.Static))
                {
                    if (method.Name == "Combine" && method.GetParameters().Length == 2)
                    {
                        delegateMethod = method;
                        break;
                    }
                }

                il.Call(delegateMethod);
                il.CastClass(@event.EventHandlerType);
                il.StoreLocal(locals[2]);

                il.LoadArgument(0);
                il.LoadFieldAddress(fieldBuilder);
                il.LoadLocal(locals[2]);
                il.LoadLocal(locals[1]);

                foreach (var method in typeof(System.Threading.Interlocked).GetMethods(BindingFlags.Public | BindingFlags.Static))
                {
                    if (method.Name == "CompareExchange" && method.IsGenericMethod && method.GetParameters().Length == 3)
                    {
                        delegateMethod = method;
                        break;
                    }
                }
                il.Call(delegateMethod.MakeGenericMethod(new[] { @event.EventHandlerType }));
                il.StoreLocal(locals[0]);
                il.LoadLocal(locals[0]);
                il.LoadLocal(locals[1]);
                il.UnsignedBranchIfNotEqual(label);
                il.Return();

                @eventBuilder.SetAddOnMethod(methodBuilder);
            }

            if (removeMethod != null)
            {
                if (fieldBuilder == null)
                {
                    fieldBuilder = typeBuilder.DefineField(@event.Name, @event.EventHandlerType, FieldAttributes.Private);
                }

                /*泛型方法和基本方法有什么不同*/
                var parameters     = removeMethod.GetParameters();
                var parameterTypes = new List <Type>(parameters.Length);
                var voidReturn     = removeMethod.ReturnType == typeof(void);

                foreach (var parameter in parameters)
                {
                    parameterTypes.Add(parameter.ParameterType);
                }

                var attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName;
                if (!buildInterface)
                {
                    attributes = MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig;
                }

                var methodBuilder = typeBuilder.DefineMethod(removeMethod.Name,
                                                             attributes,
                                                             removeMethod.CallingConvention,
                                                             removeMethod.ReturnType, parameterTypes.ToArray());

                /*fix argument length*/
                parameterTypes.Insert(0, sourceTypeOrInterfaceType);
                var il     = new MockEmitBuilder(methodBuilder.GetILGenerator(), removeMethod.CallingConvention, removeMethod.ReturnType, parameterTypes.ToArray());
                var locals = new[]
                {
                    il.DeclareLocal(@event.EventHandlerType),
                    il.DeclareLocal(@event.EventHandlerType),
                    il.DeclareLocal(@event.EventHandlerType),
                };
                var label = il.DefineLabel();

                il.LoadArgument(0);
                il.LoadField(fieldBuilder);
                il.StoreLocal(locals[0]);

                il.MarkLabel(label);
                il.LoadLocal(locals[0]);
                il.StoreLocal(locals[1]);
                il.LoadLocal(locals[1]);
                il.LoadArgument(1);

                MethodInfo delegateMethod = null;
                foreach (var method in typeof(System.Delegate).GetMethods(BindingFlags.Public | BindingFlags.Static))
                {
                    if (method.Name == "Remove" && method.GetParameters().Length == 2)
                    {
                        delegateMethod = method;
                        break;
                    }
                }

                il.Call(delegateMethod);
                il.CastClass(@event.EventHandlerType);
                il.StoreLocal(locals[2]);

                il.LoadArgument(0);
                il.LoadFieldAddress(fieldBuilder);
                il.LoadLocal(locals[2]);
                il.LoadLocal(locals[1]);

                foreach (var method in typeof(System.Threading.Interlocked).GetMethods(BindingFlags.Public | BindingFlags.Static))
                {
                    if (method.Name == "CompareExchange" && method.IsGenericMethod && method.GetParameters().Length == 3)
                    {
                        delegateMethod = method;
                        break;
                    }
                }
                il.Call(delegateMethod.MakeGenericMethod(new[] { @event.EventHandlerType }));
                il.StoreLocal(locals[0]);
                il.LoadLocal(locals[0]);
                il.LoadLocal(locals[1]);
                il.UnsignedBranchIfNotEqual(label);
                il.Return();

                @eventBuilder.SetRemoveOnMethod(methodBuilder);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// 构建属性
        /// </summary>
        /// <param name="member"></param>
        /// <param name="members"></param>
        /// <param name="exists"></param>
        /// <param name="typeBuilder">类型构建</param>
        /// <param name="sourceTypeOrInterfaceType">假如是承继父类的,则callBase就能生效</param>
        /// <param name="buildInterface">构建接口</param>
        protected virtual void BuildProperty(MemberInfo member, MemberInfo[] members, List <MemberInfo> exists, TypeBuilder typeBuilder, Type sourceTypeOrInterfaceType, bool @buildInterface)
        {
            var property = member as PropertyInfo;

            exists.Add(property);
            var        getName = string.Concat("get_", property.Name);
            var        setName = string.Concat("set_", property.Name);
            MethodInfo getMethod = null, setMethod = null;

            foreach (var m in members)
            {
                if (m.MemberType == MemberTypes.Method)
                {
                    if (getName == m.Name)
                    {
                        getMethod = (MethodInfo)m;
                        exists.Add(m);
                        if (setMethod != null)
                        {
                            break;
                        }
                    }
                    else if (setName == m.Name)
                    {
                        setMethod = (MethodInfo)m;
                        exists.Add(m);
                        if (getMethod != null)
                        {
                            break;
                        }
                    }
                }
            }

            foreach (var found in this.rules)
            {
                if (found.Property == property)
                {
                    if (getMethod != null)
                    {
                        this.BuildMethod(getMethod, members, exists, typeBuilder, sourceTypeOrInterfaceType, buildInterface, found);
                    }

                    if (setMethod != null)
                    {
                        /*泛型方法和基本方法有什么不同*/
                        var parameters     = setMethod.GetParameters();
                        var parameterTypes = new List <Type>(parameters.Length);
                        foreach (var parameter in parameters)
                        {
                            parameterTypes.Add(parameter.ParameterType);
                        }

                        var attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName;
                        if (!buildInterface)
                        {
                            attributes = MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig;
                        }

                        var methodBuilder = typeBuilder.DefineMethod(setMethod.Name,
                                                                     attributes,
                                                                     setMethod.CallingConvention,
                                                                     setMethod.ReturnType, parameterTypes.ToArray());

                        /*fix argument length*/
                        parameterTypes.Insert(0, sourceTypeOrInterfaceType);

                        var il = new MockEmitBuilder(methodBuilder.GetILGenerator(), setMethod.CallingConvention, setMethod.ReturnType, parameterTypes.ToArray());
                        il.Return();
                    }
                }
            }
        }