/// <summary> /// Each of the specialized 'peek' methods copies the appropriate field value of an instance of T /// into the provided buffer. So, the call is 'peek(userObject, ref destination)' and the logic is /// indentical to 'destination = userObject.##FIELD##', where ##FIELD## is defined per peek method. /// </summary> internal static Delegate GeneratePeek <TOwn, TRow>(InternalSchemaDefinition.Column column) { switch (column.MemberInfo) { case FieldInfo fieldInfo: Type fieldType = fieldInfo.FieldType; var assignmentOpCode = GetAssignmentOpCode(fieldType); Func <FieldInfo, OpCode, Delegate> func = GeneratePeek <TOwn, TRow, int>; var methInfo = func.GetMethodInfo().GetGenericMethodDefinition() .MakeGenericMethod(typeof(TOwn), typeof(TRow), fieldType); return((Delegate)methInfo.Invoke(null, new object[] { fieldInfo, assignmentOpCode })); case PropertyInfo propertyInfo: Type propertyType = propertyInfo.PropertyType; var assignmentOpCodeProp = GetAssignmentOpCode(propertyType); Func <PropertyInfo, OpCode, Delegate> funcProp = GeneratePeek <TOwn, TRow, int>; var methInfoProp = funcProp.GetMethodInfo().GetGenericMethodDefinition() .MakeGenericMethod(typeof(TOwn), typeof(TRow), propertyType); return((Delegate)methInfoProp.Invoke(null, new object[] { propertyInfo, assignmentOpCodeProp })); default: Contracts.Assert(false); throw Contracts.ExceptNotSupp("Expected a FieldInfo or a PropertyInfo"); } }
/// <summary> /// Each of the specialized 'peek' methods copies the appropriate field value of an instance of T /// into the provided buffer. So, the call is 'peek(userObject, ref destination)' and the logic is /// indentical to 'destination = userObject.##FIELD##', where ##FIELD## is defined per peek method. /// </summary> internal static Delegate GeneratePeek <TOwn, TRow>(InternalSchemaDefinition.Column column) { switch (column.MemberInfo) { case FieldInfo fieldInfo: Type fieldType = fieldInfo.FieldType; var assignmentOpCode = GetAssignmentOpCode(fieldType, fieldInfo.GetCustomAttributes()); return(Utils.MarshalInvoke(_generatePeekFieldMethodInfo, typeof(TOwn), typeof(TRow), fieldType, fieldInfo, assignmentOpCode)); case PropertyInfo propertyInfo: Type propertyType = propertyInfo.PropertyType; var assignmentOpCodeProp = GetAssignmentOpCode(propertyType, propertyInfo.GetCustomAttributes()); return(Utils.MarshalInvoke(_generatePeekPropertyMethodInfo, typeof(TOwn), typeof(TRow), propertyType, propertyInfo, assignmentOpCodeProp)); default: Contracts.Assert(false); throw Contracts.ExceptNotSupp("Expected a FieldInfo or a PropertyInfo"); } }
private static OpCode GetAssignmentOpCode(Type t, IEnumerable <Attribute> attributes) { // REVIEW: This should be a Dictionary<Type, OpCode> based solution. // DvTypes, strings, arrays, all nullable types, VBuffers and RowId. if (t == typeof(ReadOnlyMemory <char>) || t == typeof(string) || t.IsArray || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(VBuffer <>)) || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable <>)) || t == typeof(DateTime) || t == typeof(DateTimeOffset) || t == typeof(TimeSpan) || t == typeof(DataViewRowId) || DataViewTypeManager.Knows(t, attributes)) { return(OpCodes.Stobj); } // Simple primitive types. if (t == typeof(Single)) { return(OpCodes.Stind_R4); } if (t == typeof(Double)) { return(OpCodes.Stind_R8); } if (t == typeof(sbyte) || t == typeof(byte) || t == typeof(bool)) { return(OpCodes.Stind_I1); } if (t == typeof(short) || t == typeof(ushort)) { return(OpCodes.Stind_I2); } if (t == typeof(int) || t == typeof(uint)) { return(OpCodes.Stind_I4); } if (t == typeof(long) || t == typeof(ulong)) { return(OpCodes.Stind_I8); } throw Contracts.ExceptNotSupp("Type '{0}' is not supported.", t.FullName); }