private readonly String LambdaClassName; // Generated name for the generated class "X$$Lambda$1" /// <summary> /// General meta-factory constructor, supporting both standard cases and /// allowing for uncommon options such as serialization or bridging. /// </summary> /// <param name="caller"> Stacked automatically by VM; represents a lookup context /// with the accessibility privileges of the caller. </param> /// <param name="invokedType"> Stacked automatically by VM; the signature of the /// invoked method, which includes the expected static /// type of the returned lambda object, and the static /// types of the captured arguments for the lambda. In /// the event that the implementation method is an /// instance method, the first argument in the invocation /// signature will correspond to the receiver. </param> /// <param name="samMethodName"> Name of the method in the functional interface to /// which the lambda or method reference is being /// converted, represented as a String. </param> /// <param name="samMethodType"> Type of the method in the functional interface to /// which the lambda or method reference is being /// converted, represented as a MethodType. </param> /// <param name="implMethod"> The implementation method which should be called (with /// suitable adaptation of argument types, return types, /// and adjustment for captured arguments) when methods of /// the resulting functional interface instance are invoked. </param> /// <param name="instantiatedMethodType"> The signature of the primary functional /// interface method after type variables are /// substituted with their instantiation from /// the capture site </param> /// <param name="isSerializable"> Should the lambda be made serializable? If set, /// either the target type or one of the additional SAM /// types must extend {@code Serializable}. </param> /// <param name="markerInterfaces"> Additional interfaces which the lambda object /// should implement. </param> /// <param name="additionalBridges"> Method types for additional signatures to be /// bridged to the implementation method </param> /// <exception cref="LambdaConversionException"> If any of the meta-factory protocol /// invariants are violated </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, String samMethodName, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, boolean isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) throws LambdaConversionException public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, String samMethodName, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, bool isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) : base(caller, invokedType, samMethodName, samMethodType, implMethod, instantiatedMethodType, isSerializable, markerInterfaces, additionalBridges) { ImplMethodClassName = ImplDefiningClass.Name.Replace('.', '/'); ImplMethodName = ImplInfo.Name; ImplMethodDesc = ImplMethodType.ToMethodDescriptorString(); ImplMethodReturnClass = (ImplKind == MethodHandleInfo.REF_newInvokeSpecial) ? ImplDefiningClass : ImplMethodType.ReturnType(); ConstructorType = invokedType.ChangeReturnType(Void.TYPE); LambdaClassName = TargetClass.Name.Replace('.', '/') + "$$Lambda$" + Counter.IncrementAndGet(); Cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.ParameterCount(); if (parameterCount > 0) { ArgNames = new String[parameterCount]; ArgDescs = new String[parameterCount]; for (int i = 0; i < parameterCount; i++) { ArgNames[i] = "arg$" + (i + 1); ArgDescs[i] = BytecodeDescriptor.unparse(invokedType.ParameterType(i)); } } else { ArgNames = ArgDescs = EMPTY_STRING_ARRAY; } }
/// <summary> /// Convert an argument of type 'arg' to be passed to 'target' assuring that it is 'functional'. /// Insert the needed conversion instructions in the method code. </summary> /// <param name="arg"> </param> /// <param name="target"> </param> /// <param name="functional"> </param> internal virtual void ConvertType(Class arg, Class target, Class functional) { if (arg.Equals(target) && arg.Equals(functional)) { return; } if (arg == Void.TYPE || target == Void.TYPE) { return; } if (arg.Primitive) { Wrapper wArg = Wrapper.forPrimitiveType(arg); if (target.Primitive) { // Both primitives: widening Widen(wArg, Wrapper.forPrimitiveType(target)); } else { // Primitive argument to reference target String dTarget = BytecodeDescriptor.unparse(target); Wrapper wPrimTarget = WrapperOrNullFromDescriptor(dTarget); if (wPrimTarget != null) { // The target is a boxed primitive type, widen to get there before boxing Widen(wArg, wPrimTarget); Box(wPrimTarget); } else { // Otherwise, box and cast Box(wArg); Cast(WrapperName(wArg), dTarget); } } } else { String dArg = BytecodeDescriptor.unparse(arg); String dSrc; if (functional.Primitive) { dSrc = dArg; } else { // Cast to convert to possibly more specific type, and generate CCE for invalid arg dSrc = BytecodeDescriptor.unparse(functional); Cast(dArg, dSrc); } String dTarget = BytecodeDescriptor.unparse(target); if (target.Primitive) { Wrapper wTarget = ToWrapper(dTarget); // Reference argument to primitive target Wrapper wps = WrapperOrNullFromDescriptor(dSrc); if (wps != null) { if (wps.Signed || wps.Floating) { // Boxed number to primitive Unbox(WrapperName(wps), wTarget); } else { // Character or Boolean Unbox(WrapperName(wps), wps); Widen(wps, wTarget); } } else { // Source type is reference type, but not boxed type, // assume it is super type of target type String intermediate; if (wTarget.Signed || wTarget.Floating) { // Boxed number to primitive intermediate = "java/lang/Number"; } else { // Character or Boolean intermediate = WrapperName(wTarget); } Cast(dSrc, intermediate); Unbox(intermediate, wTarget); } } else { // Both reference types: just case to target type Cast(dSrc, dTarget); } } }