private Action <TRow> GenerateSetter(IRow input, int index, InternalSchemaDefinition.Column column, Delegate poke, Delegate peek) { var colType = input.Schema.GetColumnType(index); var fieldType = column.OutputType; var genericType = fieldType; Func <IRow, int, Delegate, Delegate, Action <TRow> > del; if (fieldType.IsArray) { Ch.Assert(colType.IsVector); // VBuffer<ReadOnlyMemory<char>> -> String[] if (fieldType.GetElementType() == typeof(string)) { Ch.Assert(colType.ItemType.IsText); 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.ItemType.RawType == Nullable.GetUnderlyingType(fieldType.GetElementType())); } else { Ch.Assert(colType.ItemType.RawType == fieldType.GetElementType()); } del = CreateDirectVBufferSetter <int>; genericType = fieldType.GetElementType(); } else if (colType.IsVector) { // VBuffer<T> -> VBuffer<T> // REVIEW: Do we care about accomodating VBuffer<string> -> VBuffer<ReadOnlyMemory<char>>? Ch.Assert(fieldType.IsGenericType); Ch.Assert(fieldType.GetGenericTypeDefinition() == typeof(VBuffer <>)); Ch.Assert(fieldType.GetGenericArguments()[0] == colType.ItemType.RawType); del = CreateVBufferToVBufferSetter <int>; genericType = colType.ItemType.RawType; } else if (colType.IsPrimitive) { if (fieldType == typeof(string)) { // ReadOnlyMemory<char> -> String Ch.Assert(colType.IsText); 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 { // 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 })); }
//private Delegate CreateGetter(SchemaProxy schema, int index, Delegate peek) private Delegate CreateGetter(ColumnType colType, InternalSchemaDefinition.Column column, Delegate peek) { var outputType = column.OutputType; var genericType = outputType; Func <Delegate, Delegate> del; if (outputType.IsArray) { Host.Assert(colType.IsVector); // String[] -> ReadOnlyMemory<char> if (outputType.GetElementType() == typeof(string)) { Host.Assert(colType.ItemType.IsText); return(CreateConvertingArrayGetterDelegate <string, ReadOnlyMemory <char> >(peek, x => x != null ? x.AsMemory() : ReadOnlyMemory <char> .Empty)); } // T[] -> VBuffer<T> if (outputType.GetElementType().IsGenericType&& outputType.GetElementType().GetGenericTypeDefinition() == typeof(Nullable <>)) { Host.Assert(Nullable.GetUnderlyingType(outputType.GetElementType()) == colType.ItemType.RawType); } else { Host.Assert(outputType.GetElementType() == colType.ItemType.RawType); } del = CreateDirectArrayGetterDelegate <int>; genericType = outputType.GetElementType(); } else if (colType.IsVector) { // VBuffer<T> -> VBuffer<T> // REVIEW: Do we care about accomodating VBuffer<string> -> ReadOnlyMemory<char>? Host.Assert(outputType.IsGenericType); Host.Assert(outputType.GetGenericTypeDefinition() == typeof(VBuffer <>)); Host.Assert(outputType.GetGenericArguments()[0] == colType.ItemType.RawType); del = CreateDirectVBufferGetterDelegate <int>; genericType = colType.ItemType.RawType; } else if (colType.IsPrimitive) { if (outputType == typeof(string)) { // String -> ReadOnlyMemory<char> Host.Assert(colType.IsText); return(CreateConvertingGetterDelegate <String, ReadOnlyMemory <char> >(peek, x => x != null ? x.AsMemory() : ReadOnlyMemory <char> .Empty)); } // T -> T if (outputType.IsGenericType && outputType.GetGenericTypeDefinition() == typeof(Nullable <>)) { Host.Assert(colType.RawType == Nullable.GetUnderlyingType(outputType)); } else { Host.Assert(colType.RawType == outputType); } del = CreateDirectGetterDelegate <int>; } else { // REVIEW: Is this even possible? throw Host.ExceptNotSupp("Type '{0}' is not yet supported.", outputType.FullName); } return(Utils.MarshalInvoke(del, genericType, peek)); }