/// <summary>
        /// Given a type and name for a variable, returns whether this appears to be a vector type,
        /// and also the associated data type for this type. If a valid data type could not
        /// be determined, this will throw.
        /// </summary>
        /// <param name="name">The name of the variable to inspect.</param>
        /// <param name="rawType">The type of the variable to inspect.</param>
        /// <param name="attributes">Attribute of <paramref name="rawType"/>. It can be <see langword="null"/> if attributes don't exist.</param>
        /// <param name="isVector">Whether this appears to be a vector type.</param>
        /// <param name="itemType">
        /// The corresponding <see cref="PrimitiveDataViewType"/> RawType of the type, or items of this type if vector.
        /// </param>
        public static void GetVectorAndItemType(string name, Type rawType, IEnumerable <Attribute> attributes, out bool isVector, out Type itemType)
        {
            // Determine whether this is a vector, and also determine the raw item type.
            isVector = true;
            if (rawType.IsArray)
            {
                itemType = rawType.GetElementType();
            }
            else if (rawType.IsGenericType && rawType.GetGenericTypeDefinition() == typeof(VBuffer <>))
            {
                itemType = rawType.GetGenericArguments()[0];
            }
            else
            {
                itemType = rawType;
                isVector = false;
            }

            // The internal type of string is ReadOnlyMemory<char>. That is, string will be stored as ReadOnlyMemory<char> in IDataView.
            if (itemType == typeof(string))
            {
                itemType = typeof(ReadOnlyMemory <char>);
            }
            // Check if the itemType extracted from rawType is supported by ML.NET's type system.
            // It must be one of either ML.NET's pre-defined types or custom types registered by the user.
            else if (!itemType.TryGetDataKind(out _) && !DataViewTypeManager.Knows(itemType, attributes))
            {
                throw Contracts.ExceptParam(nameof(rawType), "Could not determine an IDataView type for member {0}", name);
            }
        }
예제 #2
0
 /// <summary>
 /// Given a type and name for a variable, returns whether this appears to be a vector type,
 /// and also the associated data type for this type. If a valid data type could not
 /// be determined, this will throw.
 /// </summary>
 /// <param name="name">The name of the variable to inspect.</param>
 /// <param name="rawType">The type of the variable to inspect.</param>
 /// <param name="attributes">Attribute of <paramref name="rawType"/>. It can be <see langword="null"/> if attributes don't exist.</param>
 /// <param name="isVector">Whether this appears to be a vector type.</param>
 /// <param name="itemType">
 /// The corresponding <see cref="PrimitiveDataViewType"/> RawType of the type, or items of this type if vector.
 /// </param>
 public static void GetVectorAndItemType(string name, Type rawType, IEnumerable <Attribute> attributes, out bool isVector, out Type itemType)
 {
     GetMappedType(rawType, out itemType, out isVector);
     // Check if the itemType extracted from rawType is supported by ML.NET's type system.
     // It must be one of either ML.NET's pre-defined types or custom types registered by the user.
     if (!itemType.TryGetDataKind(out _) && !DataViewTypeManager.Knows(itemType, attributes))
     {
         throw Contracts.ExceptParam(nameof(rawType), "Could not determine an IDataView type and registered custom types for member {0}", name);
     }
 }
예제 #3
0
        private static void ValidateMemberInfo(MemberInfo memberInfo, IDataView data)
        {
            if (!SchemaDefinition.NeedToCheckMemberInfo(memberInfo))
            {
                return;
            }

            var mappingNameAttr = memberInfo.GetCustomAttribute <ColumnNameAttribute>();
            var singleName      = mappingNameAttr?.Name ?? memberInfo.Name;

            Type actualType = null;
            bool isVector   = false;
            IEnumerable <Attribute> customAttributes = null;

            switch (memberInfo)
            {
            case FieldInfo fieldInfo:
                InternalSchemaDefinition.GetMappedType(fieldInfo.FieldType, out actualType, out isVector);
                customAttributes = fieldInfo.GetCustomAttributes();
                break;

            case PropertyInfo propertyInfo:
                InternalSchemaDefinition.GetMappedType(propertyInfo.PropertyType, out actualType, out isVector);
                customAttributes = propertyInfo.GetCustomAttributes();
                break;

            default:
                Contracts.Assert(false);
                throw Contracts.ExceptNotSupp("Expected a FieldInfo or a PropertyInfo");
            }

            if (!actualType.TryGetDataKind(out _) && !DataViewTypeManager.Knows(actualType, customAttributes))
            {
                int colIndex;
                data.Schema.TryGetColumnIndex(singleName, out colIndex);
                DataViewType expectedType = data.Schema[colIndex].Type;
                if (!actualType.Equals(expectedType.RawType))
                {
                    throw Contracts.ExceptParam(nameof(actualType), $"The expected type '{expectedType.RawType}' does not match the type of the '{singleName}' member: '{actualType}'. Please change the {singleName} member to '{expectedType.RawType}'");
                }
            }
        }
예제 #4
0
            private Action <TRow> GenerateSetter(DataViewRow input, int index, InternalSchemaDefinition.Column column, Delegate poke, Delegate peek)
            {
                var colType     = input.Schema[index].Type;
                var fieldType   = column.OutputType;
                var genericType = fieldType;
                Func <DataViewRow, int, Delegate, Delegate, Action <TRow> > del;

                if (fieldType.IsArray)
                {
                    Ch.Assert(colType is VectorDataViewType);
                    // VBuffer<ReadOnlyMemory<char>> -> String[]
                    if (fieldType.GetElementType() == typeof(string))
                    {
                        Ch.Assert(colType.GetItemType() is TextDataViewType);
                        return(CreateConvertingVBufferSetter <ReadOnlyMemory <char>, string>(input, index, poke, peek, x => x.ToString()));
                    }

                    // VBuffer<T> -> T[]
                    if (fieldType.GetElementType().IsGenericType&& fieldType.GetElementType().GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        Ch.Assert(colType.GetItemType().RawType == Nullable.GetUnderlyingType(fieldType.GetElementType()));
                    }
                    else
                    {
                        Ch.Assert(colType.GetItemType().RawType == fieldType.GetElementType());
                    }
                    del         = CreateDirectVBufferSetter <int>;
                    genericType = fieldType.GetElementType();
                }
                else if (colType is VectorDataViewType vectorType)
                {
                    // VBuffer<T> -> VBuffer<T>
                    // REVIEW: Do we care about accommodating VBuffer<string> -> VBuffer<ReadOnlyMemory<char>>?
                    Ch.Assert(fieldType.IsGenericType);
                    Ch.Assert(fieldType.GetGenericTypeDefinition() == typeof(VBuffer <>));
                    Ch.Assert(fieldType.GetGenericArguments()[0] == vectorType.ItemType.RawType);
                    del         = CreateVBufferToVBufferSetter <int>;
                    genericType = vectorType.ItemType.RawType;
                }
                else if (colType is PrimitiveDataViewType)
                {
                    if (fieldType == typeof(string))
                    {
                        // ReadOnlyMemory<char> -> String
                        Ch.Assert(colType is TextDataViewType);
                        Ch.Assert(peek == null);
                        return(CreateConvertingActionSetter <ReadOnlyMemory <char>, string>(input, index, poke, x => x.ToString()));
                    }

                    // T -> T
                    if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        Ch.Assert(colType.RawType == Nullable.GetUnderlyingType(fieldType));
                    }
                    else
                    {
                        Ch.Assert(colType.RawType == fieldType);
                    }

                    del = CreateDirectSetter <int>;
                }
                else if (DataViewTypeManager.Knows(colType))
                {
                    del = CreateDirectSetter <int>;
                }
                else
                {
                    // REVIEW: Is this even possible?
                    throw Ch.ExceptNotImpl("Type '{0}' is not yet supported.", column.OutputType.FullName);
                }
                MethodInfo meth = del.GetMethodInfo().GetGenericMethodDefinition().MakeGenericMethod(genericType);

                return((Action <TRow>)meth.Invoke(this, new object[] { input, index, poke, peek }));
            }