Ejemplo n.º 1
0
        /// <summary>
        /// Finds the marshaller for given <see cref="TypeReference"/> and <see cref="MarshalInfo"/>.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="marshalInfo">The marshal information.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException">
        /// </exception>
        public static Marshaller FindMarshallerForType(TypeReference type, MarshalInfo marshalInfo)
        {
            // First, check the cache
            // TODO: Take marshalInfo into account
            Marshaller marshaller;

            if (marshallers.TryGetValue(type, out marshaller))
            {
                return(marshaller);
            }

            if (marshalInfo != null)
            {
                switch (marshalInfo.NativeType)
                {
                case NativeType.IUnknown:
                case NativeType.IntF:
                    // TODO: Implement a real marshaller for that case
                    return(new BlittableMarshaller());
                }
            }

            switch (type.MetadataType)
            {
            case MetadataType.Object:
            case MetadataType.ValueType:
            case MetadataType.Class:
            {
                // Various types with specific marshallers
                if (type.FullName == typeof(HandleRef).FullName)
                {
                    marshaller = new HandleRefMarshaller();
                    break;
                }

                if (type.FullName == typeof(StringBuilder).FullName)
                {
                    marshaller = new StringBuilderMarshaller();
                    break;
                }

                if (type.FullName == typeof(string).FullName)
                {
                    marshaller = new StringMarshaller(marshalInfo);
                    break;
                }

                var typeDefinition = type.Resolve();

                // Check if type is a delegate
                if (typeDefinition.BaseType != null && typeDefinition.BaseType.FullName == typeof(MulticastDelegate).FullName)
                {
                    marshaller = new DelegateMarshaller();
                    break;
                }

                // Check if type is a reference type
                if (!typeDefinition.IsValueType)
                {
                    return(new BlittableMarshaller());
                }

                if (typeDefinition.IsEnum)
                {
                    return(new BlittableMarshaller());
                }

                // Check if type is blittable
                if (IsBlittable(type, marshalInfo))
                {
                    marshaller = new BlittableMarshaller();
                    break;
                }

                marshaller = new StructMarshaller(type);
                break;
            }

            case MetadataType.Boolean:
                if (marshalInfo != null)
                {
                    // I1/U1 boolean don't need any marshalling
                    if (marshalInfo.NativeType == NativeType.I1 || marshalInfo.NativeType == NativeType.U1)
                    {
                        marshaller = new BlittableMarshaller();
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    // Default case: 4-byte integer
                    marshaller = new BooleanMarshaller();
                }
                break;

            case MetadataType.SByte:
            case MetadataType.Byte:
            case MetadataType.Int16:
            case MetadataType.UInt16:
            case MetadataType.Int32:
            case MetadataType.UInt32:
            case MetadataType.Int64:
            case MetadataType.UInt64:
            case MetadataType.Single:
            case MetadataType.Double:
            case MetadataType.IntPtr:
            case MetadataType.UIntPtr:
            case MetadataType.Pointer:
            case MetadataType.Char:
                marshaller = new BlittableMarshaller();
                break;

            case MetadataType.String:
                marshaller = new StringMarshaller(marshalInfo);
                break;

            case MetadataType.Array:
            {
                var elementType = ((ArrayType)type).ElementType;
                if (IsBlittable(elementType, marshalInfo))
                {
                    marshaller = new BlittableArrayMarshaller();
                    break;
                }

                marshaller = new ArrayMarshaller(FindMarshallerForType(elementType, marshalInfo));
                break;
            }

            default:
                throw new NotImplementedException(string.Format("Marshaller for type {0}", type));
            }

            marshallers[type] = marshaller;
            return(marshaller);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Finds the marshaller for given <see cref="TypeReference"/> and <see cref="MarshalInfo"/>.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="marshalInfo">The marshal information.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException">
        /// </exception>
        public static Marshaller FindMarshallerForType(TypeReference type, MarshalInfo marshalInfo)
        {
            // First, check the cache
            // TODO: Take marshalInfo into account
            Marshaller marshaller;
            if (marshallers.TryGetValue(type, out marshaller))
                return marshaller;

            if (marshalInfo != null)
            {
                switch (marshalInfo.NativeType)
                {
                    case NativeType.IUnknown:
                    case NativeType.IntF:
                        // TODO: Implement a real marshaller for that case
                        return new BlittableMarshaller();
                }
            }

            switch (type.MetadataType)
            {
                case MetadataType.Object:
                case MetadataType.ValueType:
                case MetadataType.Class:
                {
                    // Various types with specific marshallers
                    if (type.FullName == typeof(HandleRef).FullName)
                    {
                        marshaller = new HandleRefMarshaller();
                        break;
                    }

                    if (type.FullName == typeof(StringBuilder).FullName)
                    {
                        marshaller = new StringBuilderMarshaller();
                        break;
                    }

                    if (type.FullName == typeof(string).FullName)
                    {
                        marshaller = new StringMarshaller(marshalInfo);
                        break;
                    }

                    var typeDefinition = type.Resolve();

                    // Check if type is a delegate
                    if (typeDefinition.BaseType != null && typeDefinition.BaseType.FullName == typeof(MulticastDelegate).FullName)
                    {
                        marshaller = new DelegateMarshaller();
                        break;
                    }

                    // Check if type is a reference type
                    if (!typeDefinition.IsValueType)
                        return new BlittableMarshaller();

                    if (typeDefinition.IsEnum)
                        return new BlittableMarshaller();

                    // Check if type is blittable
                    if (IsBlittable(type, marshalInfo))
                    {
                        marshaller = new BlittableMarshaller();
                        break;
                    }

                    marshaller = new StructMarshaller(type);
                    break;
                }
                case MetadataType.Boolean:
                    if (marshalInfo != null)
                    {
                        // I1/U1 boolean don't need any marshalling
                        if (marshalInfo.NativeType == NativeType.I1 || marshalInfo.NativeType == NativeType.U1)
                            marshaller = new BlittableMarshaller();
                        else
                            throw new NotImplementedException();
                    }
                    else
                    {
                        // Default case: 4-byte integer
                        marshaller = new BooleanMarshaller();
                    }
                    break;
                case MetadataType.SByte:
                case MetadataType.Byte:
                case MetadataType.Int16:
                case MetadataType.UInt16:
                case MetadataType.Int32:
                case MetadataType.UInt32:
                case MetadataType.Int64:
                case MetadataType.UInt64:
                case MetadataType.Single:
                case MetadataType.Double:
                case MetadataType.IntPtr:
                case MetadataType.UIntPtr:
                case MetadataType.Pointer:
                case MetadataType.Char:
                    marshaller = new BlittableMarshaller();
                    break;
                case MetadataType.String:
                    marshaller = new StringMarshaller(marshalInfo);
                    break;
                case MetadataType.Array:
                {
                    var elementType = ((ArrayType)type).ElementType;
                    if (IsBlittable(elementType, marshalInfo))
                    {
                        marshaller = new BlittableArrayMarshaller();
                        break;
                    }

                    marshaller = new ArrayMarshaller(FindMarshallerForType(elementType, marshalInfo));
                    break;
                }
                default:
                    throw new NotImplementedException(string.Format("Marshaller for type {0}", type));
            }

            marshallers[type] = marshaller;
            return marshaller;
        }