Beispiel #1
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()
            ;
        }
Beispiel #2
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()
            ;
        }
        protected bool CallLazyInstanceInsurer(FieldBuilder field)
        {
            if (field == null)
            {
                throw new ArgumentNullException("field");
            }

            MethodBuilderHelper ensurer = Context.GetFieldInstanceEnsurer(field.Name);

            if (ensurer != null)
            {
                Context.MethodBuilder.Emitter
                .ldarg_0
                .call(ensurer);
            }

            return(ensurer != null);
        }
Beispiel #4
0
        private void BuildLazyInstanceEnsurer()
        {
            string              fieldName  = GetFieldName();
            FieldBuilder        field      = Context.GetField(fieldName);
            TypeHelper          fieldType  = new TypeHelper(field.FieldType);
            TypeHelper          objectType = new TypeHelper(GetObjectType());
            MethodBuilderHelper ensurer    = Context.TypeBuilder.DefineMethod(
                string.Format("$EnsureInstance{0}", fieldName),
                MethodAttributes.Private | MethodAttributes.HideBySig);

            EmitHelper emit = ensurer.Emitter;
            Label      end  = emit.DefineLabel();

            emit
            .ldarg_0
            .ldfld(field)
            .brtrue_s(end)
            ;

            object[]        parameters = TypeHelper.GetPropertyParameters(Context.CurrentProperty);
            ConstructorInfo ci         = objectType.GetPublicConstructor(typeof(InitContext));

            if (ci != null || objectType.IsAbstract)
            {
                CreateInitContextLazyInstance(field, fieldType, objectType, emit, parameters);
            }
            else if (parameters == null)
            {
                CreateDefaultInstance(field, fieldType, objectType, emit);
            }
            else
            {
                CreateParametrizedInstance(field, fieldType, objectType, emit, parameters);
            }

            emit
            .MarkLabel(end)
            .ret()
            ;

            Context.Items.Add("$BLToolkit.FieldInstanceEnsurer." + fieldName, ensurer);
        }
Beispiel #5
0
        private void BuildTypeProperties()
        {
            // Type.
            //
            MethodBuilderHelper method =
                _typeBuilder.DefineMethod(_accessorType.GetProperty("Type").GetGetMethod());

            method.Emitter
            .LoadType(_type)
            .ret()
            ;

            // OriginalType.
            //
            method =
                _typeBuilder.DefineMethod(_accessorType.GetProperty("OriginalType").GetGetMethod());

            method.Emitter
            .LoadType(_originalType)
            .ret()
            ;
        }
Beispiel #6
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);
        }
        public void Test()
        {
            TypeBuilderHelper typeBuilder =
                new AssemblyBuilderHelper("HelloWorld.dll").DefineType("Test", typeof(TestObject));

            // Property
            //
            PropertyInfo        propertyInfo  = typeof(TestObject).GetProperty("Property");
            MethodBuilderHelper methodBuilder = typeBuilder.DefineMethod(propertyInfo.GetGetMethod());
            EmitHelper          emit          = methodBuilder.Emitter;

            emit
            .ldc_i4(10)
            .ret()
            ;

            // Method1
            //
            MethodInfo methodInfo = typeof(TestObject).GetMethod(
                "Method1", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            methodBuilder = typeBuilder.DefineMethod(methodInfo);
            emit          = methodBuilder.Emitter;

            emit
            .ldc_i4(10)
            .ret()
            ;

            // Method2
            //
            methodInfo = typeof(TestObject).GetMethod("Method2", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            methodBuilder = typeBuilder.DefineMethod(
                "Method2",
                MethodAttributes.Virtual |
                MethodAttributes.Public |
                MethodAttributes.HideBySig |
                MethodAttributes.PrivateScope |
                MethodAttributes.VtableLayoutMask,
                typeof(int),
                new Type[] { typeof(float) });

            typeBuilder.TypeBuilder.DefineMethodOverride(methodBuilder, methodInfo);

            emit = methodBuilder.Emitter;

            emit
            .ldc_i4(10)
            .ret()
            ;

            // Create type.
            //
            Type type = typeBuilder.Create();

            TestObject obj = (TestObject)Activator.CreateInstance(type);

            Assert.AreEqual(10, obj.Property);
            Assert.AreEqual(10, obj.Method3(0));
            Assert.AreEqual(10, obj.Method2(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);

                // 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);

                MethodBuilderHelper 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);
        }
Beispiel #9
0
        private void BuildTypedGetterForNullable(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType)
        {
            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;
                    }
                }
            }

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

            if (methodInfo == null)
            {
                return;
            }

            MethodBuilderHelper method = nestedType.DefineMethod(methodInfo);
            Type nullableType          = typeof(Nullable <>).MakeGenericType(memberType);

            EmitHelper emit = method.Emitter;

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

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

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

            emit
            .call(nullableType, "get_Value")
            .ret()
            ;
        }
Beispiel #10
0
        private void BuildCloneValueMethod(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType
            )
        {
            Type       methodType = mi.DeclaringType;
            MethodInfo getMethod  = null;
            MethodInfo setMethod  = 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;
                    }
                }

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

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

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

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

            EmitHelper 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
                {
                    Label 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()
            ;
        }
Beispiel #11
0
        private void BuildIsNull(
            MemberInfo mi,
            TypeBuilderHelper nestedType,
            Type memberType)
        {
            Type       methodType  = mi.DeclaringType;
            MethodInfo getMethod   = null;
            Boolean    isNullable  = TypeHelper.IsNullable(memberType);
            Boolean    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;
                    }
                }
            }

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

            if (methodInfo == null)
            {
                return;
            }

            MethodBuilderHelper method = nestedType.DefineMethod(methodInfo);
            EmitHelper          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()
            ;
        }
Beispiel #12
0
        private void BuildSetter(MemberInfo mi, TypeBuilderHelper nestedType)
        {
            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;
                    }
                }
            }
            //else if (((FieldInfo)mi).IsLiteral)
            //	return;

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

            EmitHelper emit = method.Emitter;

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

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

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

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

            emit
            .ret()
            ;

            nestedType.DefineMethod(_memberAccessor.GetProperty("HasSetter").GetGetMethod()).Emitter
            .ldc_i4_1
            .ret()
            ;
        }
Beispiel #13
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()
            ;
        }
Beispiel #14
0
        void BuildCreateInstanceMethods()
        {
            bool            isValueType  = _type.IsValueType;
            ConstructorInfo baseDefCtor  = isValueType? null: _type.GetPublicDefaultConstructor();
            ConstructorInfo baseInitCtor = _type.GetPublicConstructor(typeof(InitContext));

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

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

            if (baseDefCtor != null)
            {
                method.Emitter
                .newobj(baseDefCtor)
                .ret()
                ;
            }
            else if (isValueType)
            {
                LocalBuilder 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)
            {
                LocalBuilder locObj = method.Emitter.DeclareLocal(_type);

                method.Emitter
                .ldloca(locObj)
                .initobj(_type)
                .ldloc(locObj)
                .box(_type)
                .ret()
                ;
            }
            else
            {
                method.Emitter
                .newobj(baseDefCtor)
                .ret()
                ;
            }
        }
Beispiel #15
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);
        }