private WriteBack AddressOfWriteBackCore(IndexExpression node) { // emit instance, if any LocalBuilder?instanceLocal = null; Type? instanceType = null; if (node.Object != null) { EmitInstance(node.Object, out instanceType); // store in local IL.Emit(OpCodes.Dup); IL.Emit(OpCodes.Stloc, instanceLocal = GetInstanceLocal(instanceType)); } // Emit indexes. We don't allow byref args, so no need to worry // about write-backs or EmitAddress var n = node.ArgumentCount; var args = new LocalBuilder[n]; for (var i = 0; i < n; i++) { var arg = node.GetArgument(i); EmitExpression(arg); var argLocal = GetLocal(arg.Type); IL.Emit(OpCodes.Dup); IL.Emit(OpCodes.Stloc, argLocal); args[i] = argLocal; } // emit the get EmitGetIndexCall(node, instanceType); // emit the address of the value var valueLocal = GetLocal(node.Type); IL.Emit(OpCodes.Stloc, valueLocal); IL.Emit(OpCodes.Ldloca, valueLocal); // Set the property after the method call // don't re-evaluate anything return(@this => { if (instanceLocal != null) { @this.IL.Emit(OpCodes.Ldloc, instanceLocal); @this.FreeLocal(instanceLocal); } foreach (var arg in args) { @this.IL.Emit(OpCodes.Ldloc, arg); @this.FreeLocal(arg); } @this.IL.Emit(OpCodes.Ldloc, valueLocal); @this.FreeLocal(valueLocal); @this.EmitSetIndexCall(node, instanceLocal?.LocalType); }); }
private LocalBuilder Imitate(Object obj, ILGenerator il) { var type = obj.GetType(); var bldr = Construct(type, il); var node = new ValueNode(obj); var props = _objectManipulator.GetPropertyResults(node, _settings); foreach (var prop in props) { LocalBuilder?liveLocal = null; switch (prop.Value) { case String str: il.Emit(OpCodes.Ldstr, str); liveLocal = il.DeclareLocal(typeof(String)); break; case Int32 i32: il.Emit(OpCodes.Ldind_I4, i32); liveLocal = il.DeclareLocal(typeof(Int32)); break; } if (liveLocal != null) { il.Emit(OpCodes.Stloc, liveLocal); SetPropertyValue(bldr, prop, liveLocal, il); } } return(bldr); }
private int WriteMembers(ClassDataContract classContract, LocalBuilder?extensionDataLocal, ClassDataContract derivedMostClassContract) { int memberCount = (classContract.BaseContract == null) ? 0 : WriteMembers(classContract.BaseContract, extensionDataLocal, derivedMostClassContract); int classMemberCount = classContract.Members !.Count; _ilg.Call(thisObj: _contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, classMemberCount); for (int i = 0; i < classMemberCount; i++, memberCount++) { DataMember member = classContract.Members[i]; Type memberType = member.MemberType; LocalBuilder?memberValue = null; _ilg.Load(_contextArg); _ilg.Call(methodInfo: member.IsGetOnlyCollection ? XmlFormatGeneratorStatics.StoreIsGetOnlyCollectionMethod : XmlFormatGeneratorStatics.ResetIsGetOnlyCollectionMethod); if (!member.EmitDefaultValue) { memberValue = LoadMemberValue(member); _ilg.IfNotDefaultValue(memberValue); } bool requiresNameAttribute = DataContractJsonSerializerImpl.CheckIfXmlNameRequiresMapping(classContract.MemberNames ![i]);
public unsafe DeserializeStaticMutableArguments(ArrayPool <byte> pool) { this.pool = pool; deserializeDictionaryEntrySegments = pool.Rent(sizeof(DeserializeDictionaryEntrySegment) * 64); used = default; ByteVariable = default; ULongVariable = default; Length = default; Position = default; Rest = default; }
private int ReadMembers(ClassDataContract classContract, bool[] requiredMembers, Label[] memberLabels, LocalBuilder memberIndexLocal, LocalBuilder?requiredIndexLocal) { Debug.Assert(_objectLocal != null); Debug.Assert(_objectType != null); int memberCount = (classContract.BaseContract == null) ? 0 : ReadMembers(classContract.BaseContract, requiredMembers, memberLabels, memberIndexLocal, requiredIndexLocal); for (int i = 0; i < classContract.Members !.Count; i++, memberCount++) { DataMember dataMember = classContract.Members[i]; Type memberType = dataMember.MemberType; _ilg.Case(memberLabels[memberCount], dataMember.Name); if (dataMember.IsRequired) { int nextRequiredIndex = memberCount + 1; for (; nextRequiredIndex < requiredMembers.Length; nextRequiredIndex++) { if (requiredMembers[nextRequiredIndex]) { break; } } _ilg.Set(requiredIndexLocal !, nextRequiredIndex); } LocalBuilder?value = null; if (dataMember.IsGetOnlyCollection) { _ilg.LoadAddress(_objectLocal); _ilg.LoadMember(dataMember.MemberInfo); value = _ilg.DeclareLocal(memberType, dataMember.Name + "Value"); _ilg.Stloc(value); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.StoreCollectionMemberInfoMethod, value); ReadValue(memberType, dataMember.Name, classContract.StableName.Namespace); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ResetCollectionMemberInfoMethod); value = ReadValue(memberType, dataMember.Name, classContract.StableName.Namespace); _ilg.LoadAddress(_objectLocal); _ilg.ConvertAddress(_objectLocal.LocalType, _objectType); _ilg.Ldloc(value); _ilg.StoreMember(dataMember.MemberInfo); } _ilg.Set(memberIndexLocal, memberCount); _ilg.EndCase(); } return(memberCount); }
private void EnsureLabelAndValue() { if (!_labelDefined) { _labelDefined = true; _label = _ilg.DefineLabel(); if (_node != null && _node.Type != typeof(void)) { _value = _ilg.DeclareLocal(_node.Type); } } }
private void WriteClass(ClassDataContract classContract) { InvokeOnSerializing(classContract); if (classContract.IsISerializable) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.WriteISerializableMethod, _xmlWriterArg, _objectLocal); } else { if (classContract.ContractNamespaces!.Length > 1) { _contractNamespacesLocal = _ilg.DeclareLocal(typeof(XmlDictionaryString[]), "contractNamespaces"); _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.ContractNamespacesField); _ilg.Store(_contractNamespacesLocal); } _memberNamesLocal = _ilg.DeclareLocal(typeof(XmlDictionaryString[]), "memberNames"); _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.MemberNamesField); _ilg.Store(_memberNamesLocal); for (int i = 0; i < classContract.ChildElementNamespaces!.Length; i++) { if (classContract.ChildElementNamespaces[i] != null) { _childElementNamespacesLocal = _ilg.DeclareLocal(typeof(XmlDictionaryString[]), "childElementNamespaces"); _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespacesProperty); _ilg.Store(_childElementNamespacesLocal); } } if (classContract.HasExtensionData) { LocalBuilder extensionDataLocal = _ilg.DeclareLocal(Globals.TypeOfExtensionDataObject, "extensionData"); _ilg.Load(_objectLocal); _ilg.ConvertValue(_objectLocal.LocalType, Globals.TypeOfIExtensibleDataObject); _ilg.LoadMember(XmlFormatGeneratorStatics.ExtensionDataProperty); _ilg.Store(extensionDataLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.WriteExtensionDataMethod, _xmlWriterArg, extensionDataLocal, -1); WriteMembers(classContract, extensionDataLocal, classContract); } else { WriteMembers(classContract, null, classContract); } } InvokeOnSerialized(classContract); }
private void ReadMembers(ClassDataContract classContract, LocalBuilder?extensionDataLocal) { int memberCount = classContract.MemberNames !.Length; _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, memberCount); BitFlagsGenerator expectedElements = new BitFlagsGenerator(memberCount, _ilg, classContract.UnderlyingType.Name + "_ExpectedElements"); byte[] requiredElements = new byte[expectedElements.GetLocalCount()]; SetRequiredElements(classContract, requiredElements); SetExpectedElements(expectedElements, 0 /*startIndex*/); LocalBuilder memberIndexLocal = _ilg.DeclareLocal(Globals.TypeOfInt, "memberIndex", -1); Label throwDuplicateMemberLabel = _ilg.DefineLabel(); Label throwMissingRequiredMembersLabel = _ilg.DefineLabel(); object forReadElements = _ilg.For(null, null, null); _ilg.Call(null, XmlFormatGeneratorStatics.MoveToNextElementMethod, _xmlReaderArg); _ilg.IfFalseBreak(forReadElements); _ilg.Call(_contextArg, JsonFormatGeneratorStatics.GetJsonMemberIndexMethod, _xmlReaderArg, _memberNamesArg, memberIndexLocal, extensionDataLocal); if (memberCount > 0) { Label[] memberLabels = _ilg.Switch(memberCount); ReadMembers(classContract, expectedElements, memberLabels, throwDuplicateMemberLabel, memberIndexLocal); _ilg.EndSwitch(); } else { _ilg.Pop(); } _ilg.EndFor(); CheckRequiredElements(expectedElements, requiredElements, throwMissingRequiredMembersLabel); Label endOfTypeLabel = _ilg.DefineLabel(); _ilg.Br(endOfTypeLabel); _ilg.MarkLabel(throwDuplicateMemberLabel); _ilg.Call(null, JsonFormatGeneratorStatics.ThrowDuplicateMemberExceptionMethod, _objectLocal, _memberNamesArg, memberIndexLocal); _ilg.MarkLabel(throwMissingRequiredMembersLabel); _ilg.Load(_objectLocal); _ilg.ConvertValue(_objectLocal.LocalType, Globals.TypeOfObject); _ilg.Load(_memberNamesArg); expectedElements.LoadArray(); LoadArray(requiredElements, "requiredElements"); _ilg.Call(JsonFormatGeneratorStatics.ThrowMissingRequiredMembersMethod); _ilg.MarkLabel(endOfTypeLabel); }
private void EmitMemberAssignment(AssignBinaryExpression node, CompilationFlags flags) { Debug.Assert(!node.IsByRef); var lvalue = (MemberExpression)node.Left; var member = lvalue.Member; // emit "this", if any Type?objectType = null; if (lvalue.Expression != null) { EmitInstance(lvalue.Expression, out objectType); } // emit value EmitExpression(node.Right); LocalBuilder?temp = null; var emitAs = flags & CompilationFlags.EmitAsTypeMask; if (emitAs != CompilationFlags.EmitAsVoidType) { // save the value so we can return it IL.Emit(OpCodes.Dup); temp = GetLocal(node.Type); IL.Emit(OpCodes.Stloc, temp); } if (member is FieldInfo info) { IL.EmitFieldSet(info); } else { // MemberExpression.Member can only be a FieldInfo or a PropertyInfo Debug.Assert(member is PropertyInfo); var prop = (PropertyInfo)member; EmitCall(objectType, prop.GetSetMethod(true)); } if (temp == null) { return; } IL.Emit(OpCodes.Ldloc, temp); FreeLocal(temp); }
internal object For(LocalBuilder?local, object?start, object?end) { ForState forState = new ForState(local, DefineLabel(), DefineLabel(), end); if (forState.Index != null) { Load(start); Stloc(forState.Index); Br(forState.TestLabel); } MarkLabel(forState.BeginLabel); _blockStack.Push(forState); return(forState); }
private void EmitIndexAssignment(AssignBinaryExpression node, CompilationFlags flags) { Debug.Assert(!node.IsByRef); var index = (IndexExpression)node.Left; var emitAs = flags & CompilationFlags.EmitAsTypeMask; // Emit instance, if calling an instance method Type?objectType = null; if (index.Object != null) { EmitInstance(index.Object, out objectType); } // Emit indexes. We don't allow byref args, so no need to worry // about writebacks or EmitAddress for (int i = 0, n = index.ArgumentCount; i < n; i++) { var arg = index.GetArgument(i); EmitExpression(arg); } // Emit value EmitExpression(node.Right); // Save the expression value, if needed LocalBuilder?temp = null; if (emitAs != CompilationFlags.EmitAsVoidType) { IL.Emit(OpCodes.Dup); temp = GetLocal(node.Type); IL.Emit(OpCodes.Stloc, temp); } EmitSetIndexCall(index, objectType); // Restore the value if (temp == null) { return; } IL.Emit(OpCodes.Ldloc, temp); FreeLocal(temp); }
private bool InvokeFactoryMethod(ClassDataContract classContract, LocalBuilder?objectId) { Debug.Assert(_objectLocal != null); if (HasFactoryMethod(classContract)) { _ilg.Load(_contextArg); _ilg.LoadAddress(_objectLocal); _ilg.ConvertAddress(_objectLocal.LocalType, Globals.TypeOfIObjectReference); _ilg.Load(objectId); _ilg.Call(XmlFormatGeneratorStatics.GetRealObjectMethod); _ilg.ConvertValue(Globals.TypeOfObject, _ilg.CurrentMethod.ReturnType); return(true); } return(false); }
public void EmittedDeserializeIsValid(Type emitterType, Type valueType, string testLiteral, object expectedResult) { if (valueType == typeof(decimal)) { expectedResult = (decimal)(double)expectedResult; } else if (valueType == typeof(decimal?)) { expectedResult = (decimal?)(double?)expectedResult; } IConverterEmitter emitter = (IConverterEmitter)Activator.CreateInstance(emitterType) !; DynamicMethod deserialize = new DynamicMethod("Deserialize", valueType, new Type[] { typeof(ReadOnlyMemory <char>), typeof(IFormatProvider) }, typeof(NumberConverterTests)); LocalBuilder? local = null; deserialize.GetILGenerator() .Emit(gen => Nullable.GetUnderlyingType(valueType) switch { { } => gen.DeclareLocal(valueType, out local),
private void EmitListInit(ListInitExpression init) { EmitExpression(init.NewExpression); LocalBuilder?loc = null; if (init.NewExpression.Type.IsValueType) { loc = GetLocal(init.NewExpression.Type); _ilg.Emit(OpCodes.Stloc, loc); _ilg.Emit(OpCodes.Ldloca, loc); } EmitListInit(init.Initializers, loc == null, init.NewExpression.Type); if (loc != null) { _ilg.Emit(OpCodes.Ldloc, loc); FreeLocal(loc); } }
private void EmitMemberInit(MemberInitExpression init) { EmitExpression(init.NewExpression); LocalBuilder?loc = null; if (init.NewExpression.Type.IsValueType && init.Bindings.Count > 0) { loc = GetLocal(init.NewExpression.Type); _ilg.Emit(OpCodes.Stloc, loc); _ilg.Emit(OpCodes.Ldloca, loc); } EmitMemberInit(init.Bindings, loc == null, init.NewExpression.Type); if (loc != null) { _ilg.Emit(OpCodes.Ldloc, loc); FreeLocal(loc); } }
private void ReadMembers(ClassDataContract classContract, LocalBuilder?extensionDataLocal) { int memberCount = classContract.MemberNames !.Length; _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, memberCount); LocalBuilder memberIndexLocal = _ilg.DeclareLocal(Globals.TypeOfInt, "memberIndex", -1); int firstRequiredMember; bool[] requiredMembers = GetRequiredMembers(classContract, out firstRequiredMember); bool hasRequiredMembers = (firstRequiredMember < memberCount); LocalBuilder?requiredIndexLocal = hasRequiredMembers ? _ilg.DeclareLocal(Globals.TypeOfInt, "requiredIndex", firstRequiredMember) : null; object forReadElements = _ilg.For(null, null, null); _ilg.Call(null, XmlFormatGeneratorStatics.MoveToNextElementMethod, _xmlReaderArg); _ilg.IfFalseBreak(forReadElements); if (hasRequiredMembers) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetMemberIndexWithRequiredMembersMethod, _xmlReaderArg, _memberNamesArg, _memberNamespacesArg, memberIndexLocal, requiredIndexLocal, extensionDataLocal); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetMemberIndexMethod, _xmlReaderArg, _memberNamesArg, _memberNamespacesArg, memberIndexLocal, extensionDataLocal); } if (memberCount > 0) { Label[] memberLabels = _ilg.Switch(memberCount); ReadMembers(classContract, requiredMembers, memberLabels, memberIndexLocal, requiredIndexLocal); _ilg.EndSwitch(); } else { _ilg.Pop(); } _ilg.EndFor(); if (hasRequiredMembers) { _ilg.If(requiredIndexLocal !, Cmp.LessThan, memberCount); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowRequiredMemberMissingExceptionMethod, _xmlReaderArg, memberIndexLocal, requiredIndexLocal, _memberNamesArg); _ilg.EndIf(); } }
private int WriteMembers(ClassDataContract classContract, LocalBuilder?extensionDataLocal, ClassDataContract derivedMostClassContract) { int memberCount = (classContract.BaseContract == null) ? 0 : WriteMembers(classContract.BaseContract, extensionDataLocal, derivedMostClassContract); LocalBuilder namespaceLocal = _ilg.DeclareLocal(typeof(XmlDictionaryString), "ns"); if (_contractNamespacesLocal == null) { _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty); } else { _ilg.LoadArrayElement(_contractNamespacesLocal, _typeIndex - 1); } _ilg.Store(namespaceLocal); int classMemberCount = classContract.Members !.Count; _ilg.Call(thisObj: _contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, classMemberCount); for (int i = 0; i < classMemberCount; i++, memberCount++) { DataMember member = classContract.Members[i]; Type memberType = member.MemberType; LocalBuilder?memberValue = null; _ilg.Load(_contextArg); _ilg.Call(methodInfo: member.IsGetOnlyCollection ? XmlFormatGeneratorStatics.StoreIsGetOnlyCollectionMethod : XmlFormatGeneratorStatics.ResetIsGetOnlyCollectionMethod); if (!member.EmitDefaultValue) { memberValue = LoadMemberValue(member); _ilg.IfNotDefaultValue(memberValue); } bool writeXsiType = CheckIfMemberHasConflict(member, classContract, derivedMostClassContract); if (writeXsiType || !TryWritePrimitive(memberType, memberValue, member.MemberInfo, arrayItemIndex: null, ns: namespaceLocal, name: null, nameIndex: i + _childElementIndex)) { WriteStartElement(memberType, classContract.Namespace, namespaceLocal, nameLocal: null, nameIndex: i + _childElementIndex); if (classContract.ChildElementNamespaces ![i + _childElementIndex] != null)
public void EmittedAppendToStringBuilderIsValid(Type emitterType, Type valueType, object testValue, string expectedResult) { if (valueType == typeof(decimal)) { testValue = (decimal)(double)testValue; } else if (valueType == typeof(decimal?)) { testValue = (decimal?)(double?)testValue; } IConverterEmitter emitter = (IConverterEmitter)Activator.CreateInstance(emitterType) !; DynamicMethod serialize = new DynamicMethod("Serialize", typeof(string), new Type[] { valueType, typeof(IFormatProvider), typeof(char) }, typeof(NumberConverterTests)); LocalBuilder? local = null; LocalBuilder? secondaryLocal = null; serialize.GetILGenerator() .Emit(gen => { if (valueType == typeof(float) || valueType == typeof(double) || valueType == typeof(decimal)) { gen.DeclareLocal(valueType, out local); } else if (Nullable.GetUnderlyingType(valueType) is Type underlyingType) { if (underlyingType == typeof(float) || underlyingType == typeof(double) || underlyingType == typeof(decimal)) { gen.DeclareLocal(typeof(Nullable <>).MakeGenericType(underlyingType), out local); gen.DeclareLocal(valueType, out secondaryLocal); } else { gen.DeclareLocal(typeof(Nullable <>).MakeGenericType(underlyingType), out local); } } }) .Newobj <StringBuilder>() .Ldarg_0() .Emit(gen => emitter.EmitAppendToStringBuilder(gen, local, secondaryLocal, null)) .Callvirt <StringBuilder>("ToString") .Ret(); string serialized = (string)serialize.Invoke(null, new[] { testValue, CultureInfo.InvariantCulture, ',' }) !; serialized.Should().Be(expectedResult); }
private Action <LambdaCompiler> AddressOfWriteBackCore(MemberExpression node) { // emit instance, if any LocalBuilder?instanceLocal = null; Type? instanceType = null; if (node.Expression != null) { EmitInstance(node.Expression, out instanceType); // store in local IL.Emit(OpCodes.Dup); instanceLocal = GetInstanceLocal(instanceType); IL.Emit(OpCodes.Stloc, instanceLocal); } var pi = (PropertyInfo)node.Member; // emit the get EmitCall(instanceType, pi.GetGetMethod(true)); // emit the address of the value var valueLocal = GetLocal(node.Type); IL.Emit(OpCodes.Stloc, valueLocal); IL.Emit(OpCodes.Ldloca, valueLocal); // Set the property after the method call // don't re-evaluate anything return(@this => { if (instanceLocal != null) { @this.IL.Emit(OpCodes.Ldloc, instanceLocal); @this.FreeLocal(instanceLocal); } @this.IL.Emit(OpCodes.Ldloc, valueLocal); @this.FreeLocal(valueLocal); @this.EmitCall(instanceLocal?.LocalType, pi.GetSetMethod(true)); }); }
private int ReadMembers(ClassDataContract classContract, BitFlagsGenerator expectedElements, Label[] memberLabels, Label throwDuplicateMemberLabel, LocalBuilder memberIndexLocal) { int memberCount = (classContract.BaseContract == null) ? 0 : ReadMembers(classContract.BaseContract, expectedElements, memberLabels, throwDuplicateMemberLabel, memberIndexLocal); for (int i = 0; i < classContract.Members !.Count; i++, memberCount++) { DataMember dataMember = classContract.Members[i]; Type memberType = dataMember.MemberType; _ilg.Case(memberLabels[memberCount], dataMember.Name); _ilg.Set(memberIndexLocal, memberCount); expectedElements.Load(memberCount); _ilg.Brfalse(throwDuplicateMemberLabel); LocalBuilder?value = null; if (dataMember.IsGetOnlyCollection) { _ilg.LoadAddress(_objectLocal); _ilg.LoadMember(dataMember.MemberInfo); value = _ilg.DeclareLocal(memberType, dataMember.Name + "Value"); _ilg.Stloc(value); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.StoreCollectionMemberInfoMethod, value); ReadValue(memberType, dataMember.Name); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ResetCollectionMemberInfoMethod); value = ReadValue(memberType, dataMember.Name); _ilg.LoadAddress(_objectLocal); _ilg.ConvertAddress(_objectLocal.LocalType, _objectType !); _ilg.Ldloc(value); _ilg.StoreMember(dataMember.MemberInfo); } ResetExpectedElements(expectedElements, memberCount); _ilg.EndCase(); } return(memberCount); }
private void CreateObject(ClassDataContract classContract) { Type type = _objectType = classContract.UnderlyingType; if (type.IsValueType && !classContract.IsNonAttributedType) { type = Globals.TypeOfValueType; } _objectLocal = _ilg.DeclareLocal(type, "objectDeserialized"); if (classContract.UnderlyingType == Globals.TypeOfDBNull) { _ilg.LoadMember(Globals.TypeOfDBNull.GetField("Value") !); _ilg.Stloc(_objectLocal); } else if (classContract.IsNonAttributedType) { if (type.IsValueType) { _ilg.Ldloca(_objectLocal); _ilg.InitObj(type); } else { _ilg.New(classContract.GetNonAttributedTypeConstructor() !); _ilg.Stloc(_objectLocal); } } else { _ilg.Call(null, XmlFormatGeneratorStatics.GetUninitializedObjectMethod, DataContract.GetIdForInitialization(classContract)); _ilg.ConvertValue(Globals.TypeOfObject, type); _ilg.Stloc(_objectLocal); } }
private void ReadCollection(CollectionDataContract collectionContract) { Type type = collectionContract.UnderlyingType; Type itemType = collectionContract.ItemType; bool isArray = (collectionContract.Kind == CollectionKind.Array); ConstructorInfo constructor = collectionContract.Constructor !; if (type.IsInterface) { switch (collectionContract.Kind) { case CollectionKind.GenericDictionary: type = Globals.TypeOfDictionaryGeneric.MakeGenericType(itemType.GetGenericArguments()); constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.EmptyTypes) !; break; case CollectionKind.Dictionary: type = Globals.TypeOfHashtable; constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Type.EmptyTypes) !; break; case CollectionKind.Collection: case CollectionKind.GenericCollection: case CollectionKind.Enumerable: case CollectionKind.GenericEnumerable: case CollectionKind.List: case CollectionKind.GenericList: type = itemType.MakeArrayType(); isArray = true; break; } } _objectLocal = _ilg.DeclareLocal(type, "objectDeserialized"); if (!isArray) { if (type.IsValueType) { _ilg.Ldloca(_objectLocal); _ilg.InitObj(type); } else { _ilg.New(constructor); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); } } bool canReadSimpleDictionary = collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary; if (canReadSimpleDictionary) { _ilg.Load(_contextArg); _ilg.LoadMember(JsonFormatGeneratorStatics.UseSimpleDictionaryFormatReadProperty); _ilg.If(); ReadSimpleDictionary(collectionContract, itemType); _ilg.Else(); } LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); bool canReadPrimitiveArray = false; if (isArray && TryReadPrimitiveArray(itemType)) { canReadPrimitiveArray = true; _ilg.IfNot(); } LocalBuilder?growingCollection = null; if (isArray) { growingCollection = _ilg.DeclareLocal(type, "growingCollection"); _ilg.NewArray(itemType, 32); _ilg.Stloc(growingCollection); } LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); object forLoop = _ilg.For(i, 0, int.MaxValue); // Empty namespace IsStartElement(_memberNamesArg, _emptyDictionaryStringArg); _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); LocalBuilder value = ReadCollectionItem(collectionContract, itemType); if (isArray) { Debug.Assert(growingCollection != null); MethodInfo ensureArraySizeMethod = XmlFormatGeneratorStatics.EnsureArraySizeMethod.MakeGenericMethod(itemType); _ilg.Call(null, ensureArraySizeMethod, growingCollection, i); _ilg.Stloc(growingCollection); _ilg.StoreArrayElement(growingCollection, i, value); } else { StoreCollectionValue(_objectLocal, value, collectionContract); } _ilg.Else(); IsEndElement(); _ilg.If(); _ilg.Break(forLoop); _ilg.Else(); HandleUnexpectedItemInCollection(i); _ilg.EndIf(); _ilg.EndIf(); _ilg.EndFor(); if (isArray) { MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod(itemType); _ilg.Call(null, trimArraySizeMethod, growingCollection, i); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal); } if (canReadPrimitiveArray) { _ilg.Else(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal); _ilg.EndIf(); } if (canReadSimpleDictionary) { _ilg.EndIf(); } }
public void EmitDeserialize(ILGenerator gen, LocalBuilder?nullableLocal, LocalBuilder?secondaryLocal, CsvColumnAttribute?attribute) => gen .Dup() .CallPropertyGet <ReadOnlyMemory <char> >("Length") .Brfalse_S(out Label @else)
public XmlFormatClassReaderDelegate GenerateClassReader(ClassDataContract classContract) { if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { return(CreateReflectionXmlClassReader(classContract)); } else { _ilg = new CodeGenerator(); bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null); try { _ilg.BeginMethod("Read" + classContract.StableName.Name + "FromXml", Globals.TypeOfXmlFormatClassReaderDelegate, memberAccessFlag); } catch (SecurityException securityException) { if (memberAccessFlag) { classContract.RequiresMemberAccessForRead(securityException); } else { throw; } } InitArgs(); CreateObject(classContract); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); InvokeOnDeserializing(classContract); LocalBuilder?objectId = null; if (HasFactoryMethod(classContract)) { objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); } if (classContract.IsISerializable) { ReadISerializable(classContract); } else { ReadClass(classContract); } _ = InvokeFactoryMethod(classContract, objectId); if (Globals.TypeOfIDeserializationCallback.IsAssignableFrom(classContract.UnderlyingType)) { _ilg.Call(_objectLocal, XmlFormatGeneratorStatics.OnDeserializationMethod, null); } InvokeOnDeserialized(classContract); if (objectId == null) { _ilg.Load(_objectLocal); // Do a conversion back from DateTimeOffsetAdapter to DateTimeOffset after deserialization. // DateTimeOffsetAdapter is used here for deserialization purposes to bypass the ISerializable implementation // on DateTimeOffset; which does not work in partial trust. if (classContract.UnderlyingType == Globals.TypeOfDateTimeOffsetAdapter) { _ilg.ConvertValue(_objectLocal.LocalType, Globals.TypeOfDateTimeOffsetAdapter); _ilg.Call(XmlFormatGeneratorStatics.GetDateTimeOffsetMethod); _ilg.ConvertValue(Globals.TypeOfDateTimeOffset, _ilg.CurrentMethod.ReturnType); } //Copy the KeyValuePairAdapter<K,T> to a KeyValuePair<K,T>. else if (classContract.IsKeyValuePairAdapter) { _ilg.Call(classContract.GetKeyValuePairMethodInfo); _ilg.ConvertValue(Globals.TypeOfKeyValuePair.MakeGenericType(classContract.KeyValuePairGenericArguments), _ilg.CurrentMethod.ReturnType); } else { _ilg.ConvertValue(_objectLocal.LocalType, _ilg.CurrentMethod.ReturnType); } } return((XmlFormatClassReaderDelegate)_ilg.EndMethod()); } }
private void ReadGetOnlyCollection(CollectionDataContract collectionContract) { Type type = collectionContract.UnderlyingType; Type itemType = collectionContract.ItemType; bool isArray = (collectionContract.Kind == CollectionKind.Array); string itemName = collectionContract.ItemName; string itemNs = collectionContract.StableName.Namespace; _objectLocal = _ilg.DeclareLocal(type, "objectDeserialized"); _ilg.Load(_contextArg); _ilg.LoadMember(XmlFormatGeneratorStatics.GetCollectionMemberMethod); _ilg.ConvertValue(Globals.TypeOfObject, type); _ilg.Stloc(_objectLocal); //check that items are actually going to be deserialized into the collection IsStartElement(_memberNamesArg, _memberNamespacesArg); _ilg.If(); _ilg.If(_objectLocal, Cmp.EqualTo, null); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowNullValueReturnedForGetOnlyCollectionExceptionMethod, type); _ilg.Else(); LocalBuilder size = _ilg.DeclareLocal(Globals.TypeOfInt, "arraySize"); if (isArray) { _ilg.Load(_objectLocal); _ilg.Call(XmlFormatGeneratorStatics.GetArrayLengthMethod); _ilg.Stloc(size); } _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); object forLoop = _ilg.For(i, 0, int.MaxValue); IsStartElement(_memberNamesArg, _memberNamespacesArg); _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); LocalBuilder value = ReadCollectionItem(collectionContract, itemType, itemName, itemNs); if (isArray) { _ilg.If(size, Cmp.EqualTo, i); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowArrayExceededSizeExceptionMethod, size, type); _ilg.Else(); _ilg.StoreArrayElement(_objectLocal, i, value); _ilg.EndIf(); } else { StoreCollectionValue(_objectLocal, value, collectionContract); } _ilg.Else(); IsEndElement(); _ilg.If(); _ilg.Break(forLoop); _ilg.Else(); HandleUnexpectedItemInCollection(i); _ilg.EndIf(); _ilg.EndIf(); _ilg.EndFor(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, _xmlReaderArg, size, _memberNamesArg, _memberNamespacesArg); _ilg.EndIf(); _ilg.EndIf(); }
private void ReadCollection(CollectionDataContract collectionContract) { Type type = collectionContract.UnderlyingType; Type itemType = collectionContract.ItemType; bool isArray = (collectionContract.Kind == CollectionKind.Array); ConstructorInfo constructor = collectionContract.Constructor !; if (type.IsInterface) { switch (collectionContract.Kind) { case CollectionKind.GenericDictionary: type = Globals.TypeOfDictionaryGeneric.MakeGenericType(itemType.GetGenericArguments()); constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, Array.Empty <Type>()) !; break; case CollectionKind.Dictionary: type = Globals.TypeOfHashtable; constructor = XmlFormatGeneratorStatics.HashtableCtor; break; case CollectionKind.Collection: case CollectionKind.GenericCollection: case CollectionKind.Enumerable: case CollectionKind.GenericEnumerable: case CollectionKind.List: case CollectionKind.GenericList: type = itemType.MakeArrayType(); isArray = true; break; } } string itemName = collectionContract.ItemName; string itemNs = collectionContract.StableName.Namespace; _objectLocal = _ilg.DeclareLocal(type, "objectDeserialized"); if (!isArray) { if (type.IsValueType) { _ilg.Ldloca(_objectLocal); _ilg.InitObj(type); } else { _ilg.New(constructor); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); } } LocalBuilder size = _ilg.DeclareLocal(Globals.TypeOfInt, "arraySize"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetArraySizeMethod); _ilg.Stloc(size); LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); bool canReadPrimitiveArray = false; if (isArray && TryReadPrimitiveArray(type, itemType, size)) { canReadPrimitiveArray = true; _ilg.IfNot(); } _ilg.If(size, Cmp.EqualTo, -1); LocalBuilder?growingCollection = null; if (isArray) { growingCollection = _ilg.DeclareLocal(type, "growingCollection"); _ilg.NewArray(itemType, 32); _ilg.Stloc(growingCollection); } LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); object forLoop = _ilg.For(i, 0, int.MaxValue); IsStartElement(_memberNamesArg, _memberNamespacesArg); _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); LocalBuilder value = ReadCollectionItem(collectionContract, itemType, itemName, itemNs); if (isArray) { Debug.Assert(growingCollection != null); MethodInfo ensureArraySizeMethod = XmlFormatGeneratorStatics.EnsureArraySizeMethod.MakeGenericMethod(itemType); _ilg.Call(null, ensureArraySizeMethod, growingCollection, i); _ilg.Stloc(growingCollection); _ilg.StoreArrayElement(growingCollection, i, value); } else { StoreCollectionValue(_objectLocal, value, collectionContract); } _ilg.Else(); IsEndElement(); _ilg.If(); _ilg.Break(forLoop); _ilg.Else(); HandleUnexpectedItemInCollection(i); _ilg.EndIf(); _ilg.EndIf(); _ilg.EndFor(); if (isArray) { MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod(itemType); _ilg.Call(null, trimArraySizeMethod, growingCollection, i); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal); } _ilg.Else(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, size); if (isArray) { _ilg.NewArray(itemType, size); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); } LocalBuilder j = _ilg.DeclareLocal(Globals.TypeOfInt, "j"); _ilg.For(j, 0, size); IsStartElement(_memberNamesArg, _memberNamespacesArg); _ilg.If(); LocalBuilder itemValue = ReadCollectionItem(collectionContract, itemType, itemName, itemNs); if (isArray) { _ilg.StoreArrayElement(_objectLocal, j, itemValue); } else { StoreCollectionValue(_objectLocal, itemValue, collectionContract); } _ilg.Else(); HandleUnexpectedItemInCollection(j); _ilg.EndIf(); _ilg.EndFor(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, _xmlReaderArg, size, _memberNamesArg, _memberNamespacesArg); _ilg.EndIf(); if (canReadPrimitiveArray) { _ilg.Else(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal); _ilg.EndIf(); } }
private LocalBuilder ReadValue(Type type, string name, string ns) { LocalBuilder value = _ilg.DeclareLocal(type, "valueRead"); LocalBuilder?nullableValue = null; int nullables = 0; while (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfNullable) { nullables++; type = type.GetGenericArguments()[0]; } PrimitiveDataContract?primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type); if ((primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) || nullables != 0 || type.IsValueType) { LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ReadAttributesMethod, _xmlReaderArg); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ReadIfNullOrRefMethod, _xmlReaderArg, type, DataContract.IsTypeSerializable(type)); _ilg.Stloc(objectId); // Deserialize null _ilg.If(objectId, Cmp.EqualTo, Globals.NullObjectId); if (nullables != 0) { _ilg.LoadAddress(value); _ilg.InitObj(value.LocalType); } else if (type.IsValueType) { ThrowValidationException(SR.Format(SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName(type))); } else { _ilg.Load(null); _ilg.Stloc(value); } // Deserialize value // Compare against Globals.NewObjectId, which is set to string.Empty _ilg.ElseIfIsEmptyString(objectId); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); if (type.IsValueType) { _ilg.IfNotIsEmptyString(objectId); ThrowValidationException(SR.Format(SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type))); _ilg.EndIf(); } if (nullables != 0) { nullableValue = value; value = _ilg.DeclareLocal(type, "innerValueRead"); } if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { _ilg.Call(_xmlReaderArg, primitiveContract.XmlFormatReaderMethod); _ilg.Stloc(value); if (!type.IsValueType) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, value); } } else { InternalDeserialize(value, type, name, ns); } // Deserialize ref _ilg.Else(); if (type.IsValueType) { ThrowValidationException(SR.Format(SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName(type))); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetExistingObjectMethod, objectId, type, name, ns); _ilg.ConvertValue(Globals.TypeOfObject, type); _ilg.Stloc(value); } _ilg.EndIf(); if (nullableValue != null) { _ilg.If(objectId, Cmp.NotEqualTo, Globals.NullObjectId); WrapNullableObject(value, nullableValue, nullables); _ilg.EndIf(); value = nullableValue; } } else { InternalDeserialize(value, type, name, ns); } return(value); }
/// <summary> /// create a method implementation that uses GetDelegateForFunctionPointer internally /// </summary> private static Action <object, IImportResolver, ICallingConventionAdapter> ImplementMethodDelegate( TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo?monitorField, bool nonTrivialAdapter) { // create the delegate type var delegateType = BizInvokeUtilities.CreateDelegateType(baseMethod, nativeCall, type, out var delegateInvoke); var paramInfos = baseMethod.GetParameters(); var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray(); var returnType = baseMethod.ReturnType; if (paramTypes.Concat(new[] { returnType }).Any(typeof(Delegate).IsAssignableFrom)) { // this isn't a problem if CallingConventionAdapters.Waterbox is a no-op, but it is otherwise: we don't // have a custom marshaller set up so the user needs to manually pump the callingconventionadapter if (nonTrivialAdapter) { throw new InvalidOperationException( "Compatibility call mode cannot use ICallingConventionAdapters for automatically marshalled delegate types!"); } } // define a field on the class to hold the delegate var field = type.DefineField( $"DelegateField{baseMethod.Name}", delegateType, FieldAttributes.Public); var method = type.DefineMethod( baseMethod.Name, MethodAttributes.Virtual | MethodAttributes.Public, CallingConventions.HasThis, returnType, paramTypes); var il = method.GetILGenerator(); Label exc = new Label(); if (monitorField != null) // monitor: enter and then begin try { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, monitorField); il.Emit(OpCodes.Callvirt, MInfo_IMonitor_Enter); exc = il.BeginExceptionBlock(); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); for (int i = 0; i < paramTypes.Length; i++) { il.Emit(OpCodes.Ldarg, (short)(i + 1)); } il.Emit(OpCodes.Callvirt, delegateInvoke); if (monitorField != null) // monitor: finally exit { LocalBuilder?loc = null; if (returnType != typeof(void)) { loc = il.DeclareLocal(returnType); il.Emit(OpCodes.Stloc, loc); } il.Emit(OpCodes.Leave, exc); il.BeginFinallyBlock(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, monitorField); il.Emit(OpCodes.Callvirt, MInfo_IMonitor_Exit); il.EndExceptionBlock(); if (returnType != typeof(void)) { il.Emit(OpCodes.Ldloc, loc !); } } il.Emit(OpCodes.Ret); type.DefineMethodOverride(method, baseMethod); return((o, dll, adapter) => { var entryPtr = dll.GetProcAddrOrThrow(entryPointName); var interopDelegate = adapter.GetDelegateForFunctionPointer(entryPtr, delegateType.CreateType()); o.GetType().GetField(field.Name).SetValue(o, interopDelegate); }); }
/// <summary> /// create a method implementation that uses calli internally /// </summary> private static Action <object, IImportResolver, ICallingConventionAdapter> ImplementMethodCalli( TypeBuilder type, MethodInfo baseMethod, CallingConvention nativeCall, string entryPointName, FieldInfo?monitorField, FieldInfo adapterField) { var paramInfos = baseMethod.GetParameters(); var paramTypes = paramInfos.Select(p => p.ParameterType).ToArray(); var paramLoadInfos = new List <ParameterLoadInfo>(); var returnType = baseMethod.ReturnType; if (returnType != typeof(void) && !returnType.IsPrimitive && !returnType.IsPointer && !returnType.IsEnum) { throw new InvalidOperationException("Only primitive return types are supported"); } // define a field on the type to hold the entry pointer var field = type.DefineField( $"EntryPtrField{baseMethod.Name}", typeof(IntPtr), FieldAttributes.Public); var method = type.DefineMethod( baseMethod.Name, MethodAttributes.Virtual | MethodAttributes.Public, CallingConventions.HasThis, returnType, paramTypes); var il = method.GetILGenerator(); Label exc = new Label(); if (monitorField != null) // monitor: enter and then begin try { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, monitorField); il.Emit(OpCodes.Callvirt, MInfo_IMonitor_Enter); exc = il.BeginExceptionBlock(); } // phase 1: empty eval stack and each parameter load thunk does any prep work it needs to do for (int i = 0; i < paramTypes.Length; i++) { // arg 0 is this, so + 1 paramLoadInfos.Add(EmitParamterLoad(il, i + 1, paramTypes[i], adapterField)); } // phase 2: actually load the individual params, leaving each one on the stack foreach (var pli in paramLoadInfos) { pli.EmitLoad(); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); il.EmitCalli( OpCodes.Calli, nativeCall, returnType == typeof(bool) ? typeof(byte) : returnType, // undo winapi style bool garbage paramLoadInfos.Select(p => p.NativeType).ToArray()); if (monitorField != null) // monitor: finally exit { LocalBuilder?loc = null; if (returnType != typeof(void)) { loc = il.DeclareLocal(returnType); il.Emit(OpCodes.Stloc, loc); } il.Emit(OpCodes.Leave, exc); il.BeginFinallyBlock(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, monitorField); il.Emit(OpCodes.Callvirt, MInfo_IMonitor_Exit); il.EndExceptionBlock(); if (returnType != typeof(void)) { il.Emit(OpCodes.Ldloc, loc !); } } // either there's a primitive on the stack and we're expected to return that primitive, // or there's nothing on the stack and we're expected to return nothing il.Emit(OpCodes.Ret); type.DefineMethodOverride(method, baseMethod); return((o, dll, adapter) => { var entryPtr = dll.GetProcAddrOrThrow(entryPointName); o.GetType().GetField(field.Name).SetValue( o, adapter.GetDepartureFunctionPointer(entryPtr, new ParameterInfo(returnType, paramTypes), o)); }); }
public void EmitAppendToStringBuilder(ILGenerator gen, LocalBuilder?nullableLocal, LocalBuilder?_, CsvColumnAttribute?attribute) => gen .Stloc(nullableLocal !)