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