Exemplo n.º 1
0
        /// <summary>
        ///   C# allows this kind of scenarios:
        ///   interface I { void M (); }
        ///   class X { public void M (); }
        ///   class Y : X, I { }
        ///
        ///   For that case, we create an explicit implementation function
        ///   I.M in Y.
        /// </summary>
        void DefineProxy(TypeSpec iface, MethodSpec base_method, MethodSpec iface_method)
        {
            // TODO: Handle nested iface names
            string proxy_name;
            var    ns = iface.MemberDefinition.Namespace;

            if (string.IsNullOrEmpty(ns))
            {
                proxy_name = iface.MemberDefinition.Name + "." + iface_method.Name;
            }
            else
            {
                proxy_name = ns + "." + iface.MemberDefinition.Name + "." + iface_method.Name;
            }

            var param = iface_method.Parameters;

            MethodBuilder proxy = container.TypeBuilder.DefineMethod(
                proxy_name,
                MethodAttributes.Private |
                MethodAttributes.HideBySig |
                MethodAttributes.NewSlot |
                MethodAttributes.CheckAccessOnOverride |
                MethodAttributes.Virtual | MethodAttributes.Final,
                CallingConventions.Standard | CallingConventions.HasThis,
                base_method.ReturnType.GetMetaInfo(), param.GetMetaInfo());

            if (iface_method.IsGeneric)
            {
                var gnames = iface_method.GenericDefinition.TypeParameters.Select(l => l.Name).ToArray();
                proxy.DefineGenericParameters(gnames);
            }

            for (int i = 0; i < param.Count; i++)
            {
                string name = param.FixedParameters [i].Name;
                ParameterAttributes attr = ParametersCompiled.GetParameterAttribute(param.FixedParameters [i].ModFlags);
                proxy.DefineParameter(i + 1, attr, name);
            }

            int top = param.Count;
            var ec  = new EmitContext(new ProxyMethodContext(container), proxy.GetILGenerator(), null, null);

            ec.EmitThis();
            // TODO: GetAllParametersArguments
            for (int i = 0; i < top; i++)
            {
                ec.EmitArgumentLoad(i);
            }

            ec.Emit(OpCodes.Call, base_method);
            ec.Emit(OpCodes.Ret);

            container.TypeBuilder.DefineMethodOverride(proxy, (MethodInfo)iface_method.GetMetaInfo());
        }
Exemplo n.º 2
0
        /// <summary>
        ///   C# allows this kind of scenarios:
        ///   interface I { void M (); }
        ///   class X { public void M (); }
        ///   class Y : X, I { }
        ///
        ///   For that case, we create an explicit implementation function
        ///   I.M in Y.
        /// </summary>
        void DefineProxy(Type iface, MethodInfo base_method, MethodInfo iface_method,
                         AParametersCollection param)
        {
            // TODO: Handle nested iface names
            string proxy_name = SimpleName.RemoveGenericArity(iface.FullName) + "." + iface_method.Name;

            MethodBuilder proxy = container.TypeBuilder.DefineMethod(
                proxy_name,
                MethodAttributes.HideBySig |
                MethodAttributes.NewSlot |
                MethodAttributes.CheckAccessOnOverride |
                MethodAttributes.Virtual,
                CallingConventions.Standard | CallingConventions.HasThis,
                base_method.ReturnType, param.GetEmitTypes());

            Type[] gargs = TypeManager.GetGenericArguments(iface_method);
            if (gargs.Length > 0)
            {
                string[] gnames = new string[gargs.Length];
                for (int i = 0; i < gargs.Length; ++i)
                {
                    gnames[i] = gargs[i].Name;
                }

#if GMCS_SOURCE
                proxy.DefineGenericParameters(gnames);
#else
                throw new NotSupportedException();
#endif
            }

            for (int i = 0; i < param.Count; i++)
            {
                string name = param.FixedParameters [i].Name;
                ParameterAttributes attr = ParametersCompiled.GetParameterAttribute(param.FixedParameters [i].ModFlags);
                proxy.DefineParameter(i + 1, attr, name);
            }

            int         top = param.Count;
            ILGenerator ig  = proxy.GetILGenerator();

            for (int i = 0; i <= top; i++)
            {
                ParameterReference.EmitLdArg(ig, i);
            }

            ig.Emit(OpCodes.Call, base_method);
            ig.Emit(OpCodes.Ret);

            container.TypeBuilder.DefineMethodOverride(proxy, iface_method);
        }
        public virtual void ApplyAttributes(MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
        {
            if (builder != null)
            {
                throw new InternalErrorException("builder already exists");
            }

            var pattrs = ParametersCompiled.GetParameterAttribute(modFlags);

            if (HasOptionalExpression)
            {
                pattrs |= ParameterAttributes.Optional;
            }

            if (mb == null)
            {
                builder = cb.DefineParameter(index, pattrs, Name);
            }
            else
            {
                builder = mb.DefineParameter(index, pattrs, Name);
            }

            if (OptAttributes != null)
            {
                OptAttributes.Emit();
            }

            if (HasDefaultValue)
            {
                //
                // Emit constant values for true constants only, the other
                // constant-like expressions will rely on default value expression
                //
                var      def_value = DefaultValue;
                Constant c         = def_value != null ? def_value.Child as Constant : default_expr as Constant;
                if (c != null)
                {
                    if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal)
                    {
                        pa.DecimalConstant.EmitAttribute(builder, (decimal)c.GetValue(), c.Location);
                    }
                    else
                    {
                        builder.SetConstant(c.GetValue());
                    }
                }
                else if (default_expr.Type.IsStruct)
                {
                    //
                    // Handles special case where default expression is used with value-type
                    //
                    // void Foo (S s = default (S)) {}
                    //
                    builder.SetConstant(null);
                }
            }

            if (parameter_type != null)
            {
                if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
                {
                    pa.Dynamic.EmitAttribute(builder);
                }
                else if (parameter_type.HasDynamicElement)
                {
                    pa.Dynamic.EmitAttribute(builder, parameter_type, Location);
                }
            }
        }