Ejemplo n.º 1
0
        /// <summary>
        /// Create a marshaller
        /// </summary>
        /// <param name="parameterType">type of the parameter to marshal</param>
        /// <param name="pInvokeMethodData">PInvoke Method specific marshal data</param>
        /// <param name="pInvokeParameterdata">PInvoke parameter specific marshal data</param>
        /// <returns>The  created Marshaller</returns>
        public static Marshaller CreateMarshaller(TypeDesc parameterType, PInvokeMethodData pInvokeMethodData, ParameterMetadata pInvokeParameterdata)
        {
            MarshallerKind marshallerKind = GetMarshallerKind(parameterType,
                                                              pInvokeParameterdata,
                                                              pInvokeMethodData,
                                                              isField: false);

            // Create the marshaller based on MarshallerKind
            Marshaller marshaller = Marshaller.CreateMarshallerInternal(marshallerKind);

            marshaller.PInvokeMethodData        = pInvokeMethodData;
            marshaller.PInvokeParameterMetadata = pInvokeParameterdata;
            marshaller.MarshallerKind           = marshallerKind;
            marshaller.NativeParameterType      = null;
            marshaller.ManagedParameterType     = parameterType;
            marshaller.Optional = pInvokeParameterdata.Optional;
            marshaller.Return   = pInvokeParameterdata.Return;
            marshaller.IsByRef  = parameterType.IsByRef;
            marshaller.In       = pInvokeParameterdata.In;
            //
            // Desktop ignores [Out] on marshaling scenarios where they don't make sense (such as passing
            // value types and string as [out] without byref).
            //
            if (parameterType.IsByRef)
            {
                // Passing as [Out] by ref is valid
                marshaller.Out = pInvokeParameterdata.Out;
            }
            else
            {
                // Passing as [Out] is valid only if it is not ValueType nor string
                if (!parameterType.IsValueType && !parameterType.IsString)
                {
                    marshaller.Out = pInvokeParameterdata.Out;
                }
            }

            if (!marshaller.In && !marshaller.Out)
            {
                //
                // Rules for in/out
                // 1. ByRef args: [in]/[out] implied by default
                // 2. StringBuilder: [in, out] by default
                // 3. non-ByRef args: [In] is implied if no [In]/[Out] is specified
                //
                if (parameterType.IsByRef)
                {
                    marshaller.In  = true;
                    marshaller.Out = true;
                }
                else if (pInvokeMethodData.IsStringBuilder(parameterType))
                {
                    marshaller.In  = true;
                    marshaller.Out = true;
                }
                else
                {
                    marshaller.In = true;
                }
            }
            return(marshaller);
        }