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