private void GenerateCreateAndChildCallCode(ILLocalVariable local) { var type = local.Type; var constructor = type.GetTypeInfo().GetConstructor(Type.EmptyTypes); if (constructor == null) { throw InvalidGraphException.NoParameterLessConstructor(type); } _il.Construct(constructor); _il.Set(local); var childTravellerInfo = _context.GetTraveller(type); var field = ILPointer.Field(ILPointer.This(), childTravellerInfo.Field); _il.InvokeMethod(field, childTravellerInfo.TravelReadMethod, _visitorVariable, local); }
private void GeneratePropertyCode(ILArgPointer graphArg, SerializableProperty target) { var extPropertyType = target.Ext; var argsField = _context.GetArgsField(target); var argsFieldVariable = ILPointer.Field(ILPointer.This(), argsField); if (extPropertyType.IsValueOrNullableOfValue()) { var isNullable = extPropertyType.Classification == TypeClassification.Nullable; var isEnum = extPropertyType.IsEnum(); var isValueType = extPropertyType.Info.IsValueType; var mediatorPropertyType = isEnum ? extPropertyType.GetUnderlyingEnumType() : extPropertyType.Ref; var valueType = !isNullable && isValueType ? Members.Nullable[mediatorPropertyType].NullableType : mediatorPropertyType; var valueLocal = _il.NewLocal(valueType); _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[valueType], argsFieldVariable, valueLocal); if (isValueType && !isNullable) { var labelValueNotFound = _il.NewLabel(); labelValueNotFound.TransferLongIfFalse(); _il.Load(valueLocal .Call(Members.Nullable[mediatorPropertyType].GetHasValue) .Negate()); var nullableHasValueLabel = _il.NewLabel(); nullableHasValueLabel.TransferLong(); labelValueNotFound.Mark(); _il.Load(true); nullableHasValueLabel.Mark(); } else { _il.Negate(); } var skipSetValueLabel = _il.NewLabel(); skipSetValueLabel.TransferLongIfTrue(); var valueToAdd = isValueType && !isNullable ? valueLocal.Call(Members.Nullable[mediatorPropertyType].GetValue) : valueLocal; _il.Set(graphArg, target.Ref, valueToAdd); skipSetValueLabel.Mark(); } else if (extPropertyType.Classification == TypeClassification.Dictionary) { var stateLocal = _il.NewLocal(typeof(ValueState)); _il.Set(stateLocal, _visitorVariable.Call(Members.VisitorTryVisit, argsFieldVariable)); var endLabel = _il.NewLabel(); endLabel.TransferLongIfTrue(stateLocal.Equal((int)ValueState.NotFound)); _il.AreEqual(stateLocal, (int)ValueState.Found); var nullLabel = _il.NewLabel(); nullLabel.TransferLongIfFalse(); var dictionaryLocal = GenerateDictionaryEnumerateCode(target.Ref.PropertyType, target.Ref.Name); _il.Set(graphArg, target.Ref, dictionaryLocal.Cast(target.Ref.PropertyType)); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, argsFieldVariable); endLabel.TransferLong(); nullLabel.Mark(); _il.Set(graphArg, target.Ref, null); endLabel.Mark(); } else if (extPropertyType.Classification == TypeClassification.Collection) { _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisit, argsFieldVariable); var stateLocal = _il.NewLocal(typeof(ValueState)); _il.Set(stateLocal); _il.AreEqual(stateLocal, (int)ValueState.NotFound); var endLabel = _il.NewLabel(); endLabel.TransferLongIfTrue(); _il.AreEqual(stateLocal, (int)ValueState.Found); var nullLabel = _il.NewLabel(); nullLabel.TransferLongIfFalse(); var collectionParam = GenerateCollectionContent(extPropertyType, target.Ref.Name); _il.Set(graphArg, target.Ref, collectionParam); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, argsFieldVariable); endLabel.TransferLong(); nullLabel.Mark(); _il.Set(graphArg, target.Ref, null); endLabel.Mark(); } else { _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisit, argsFieldVariable); var stateLocal = _il.NewLocal(typeof(ValueState)); _il.Set(stateLocal); _il.IfNotEqual(stateLocal, (int)ValueState.NotFound) .Then(() => { _il.IfEqual(stateLocal, (int)ValueState.Found) .Then(() => { var singleLocal = _il.NewLocal(extPropertyType.Ref); GenerateCreateAndChildCallCode(singleLocal); _il.Set(graphArg, target.Ref, singleLocal); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, argsFieldVariable); }).Else(() => { _il.Set(graphArg, target.Ref, null); }).End(); }).End(); } }
private void GeneratePropertyCode(ILPointer graphPointer, SerializableProperty target) { var extPropertyType = target.Ext; var argsField = _context.GetArgsField(target); var argsFieldVariable = ILPointer.Field(ILPointer.This(), argsField); if (target.Ext.IsValueOrNullableOfValue()) { var valueType = target.Ext.IsEnum() ? target.Ext.GetUnderlyingEnumType() : target.Ref.PropertyType; var propertyParameter = ILPointer.Property(graphPointer, target.Ref).AsNullable(); _il.InvokeMethod(_visitorVariable, Members.VisitorVisitValue[valueType], propertyParameter, argsFieldVariable); } else if (extPropertyType.Classification == TypeClassification.Dictionary) { var container = extPropertyType.Container.AsDictionary(); var dictionaryType = container.DictionaryInterfaceType; var cLocal = _il.NewLocal(dictionaryType); _il.Set(cLocal, ILPointer.Property(graphPointer, target.Ref).Cast(dictionaryType)); _il.InvokeMethod(_visitorVariable, Members.VisitorVisit, cLocal, argsFieldVariable); _il.IfNotEqual(cLocal, null) .Then(() => GenerateDictionaryCode(cLocal, container.ElementType)) .End(); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, cLocal, argsFieldVariable); } else if (extPropertyType.Classification == TypeClassification.Collection) { var container = extPropertyType.Container.AsCollection(); var collectionType = extPropertyType.Ref.IsArray && extPropertyType.Container.AsArray().Ranks > 1 ? extPropertyType.Ref : container.CollectionInterfaceType; var cLocal = _il.NewLocal(collectionType); _il.Set(cLocal, ILPointer.Property(graphPointer, target.Ref).Cast(collectionType)); _il.InvokeMethod(_visitorVariable, Members.VisitorVisit, cLocal, argsFieldVariable); _il.IfNotEqual(cLocal, null) .Then(() => GenerateEnumerateCollectionContentCode(extPropertyType, cLocal)) .End(); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, cLocal, argsFieldVariable); } else { var singleLocal = _il.NewLocal(target.Ref.PropertyType); _il.Set(singleLocal, ILPointer.Property(graphPointer, target.Ref)); _il.InvokeMethod(_visitorVariable, Members.VisitorVisit, singleLocal, argsFieldVariable); var checkIfNullLabel = _il.NewLabel(); checkIfNullLabel.TransferIfNull(singleLocal); GenerateChildCall(singleLocal); checkIfNullLabel.Mark(); _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, singleLocal, argsFieldVariable); } }