public void BuildTravelReadMethod() { var graphArgument = new MethodArgILCodeVariable(2, _target.Type); foreach (var property in _target.Properties) { GeneratePropertyCode(graphArgument, property); } _il.Return(); }
public void BuildTraveller() { if (_classBuilder.IsSealed) throw new InvalidOperationException("Class builder is sealed"); var target = _typeProvider.GetOrCreate(_type); var members = _dtContext.Members; var factoryArgument = new MethodArgILCodeVariable(1, members.VisitArgsFactoryType); var childTravellers = new Dictionary<Type, ChildTravellerInfo>(); var argFields = new Dictionary<SerializableProperty, FieldInfo>(); var travellerIndex = 0; foreach (var property in target.Properties) { var argField = _classBuilder.DefinePrivateField("_arg" + property.Ref.Name, members.VisitArgsType); var visitArgsCode = new CallMethodILCode(factoryArgument, members.ConstructVisitArgsMethod, property.Ref.Name); _constructorBuilder.IL.SetField(argField, visitArgsCode); argFields.Add(property, argField); Type[] types; if (!ReflectionAnalyzer.TryGetComplexTypes(property.Ext, out types)) continue; foreach (var type in types) { if (childTravellers.ContainsKey(type)) continue; var dynamicTraveller = _dtContext.Get(type); var interfaceType = typeof (IGraphTraveller<>).MakeGenericType(type); var fieldBuilder = _classBuilder.DefinePrivateField(string.Concat("_traveller", type.Name, ++travellerIndex), interfaceType); childTravellers.Add(type, new ChildTravellerInfo { Field = fieldBuilder, TravelWriteMethod = dynamicTraveller.TravelWriteMethod, TravelReadMethod = dynamicTraveller.TravelReadMethod }); var getFactoryCode = new CallMethodILCode(factoryArgument, members.ConstructVisitArgsWithTypeMethod, type); var callConstructorCode = new CallConstructorILCode(dynamicTraveller.Constructor, getFactoryCode); _constructorBuilder.IL.SetField(fieldBuilder, callConstructorCode); //_constructorBuilder.IL.SetField(fieldBuilder, dynamicTraveller.Constructor); } } _constructorBuilder.IL.Return(); var context = new TravellerContext(childTravellers, argFields); BuildWriteMethods(target, context); BuildReadMethods(target, context); _classBuilder.Seal(); _dynamicTraveller.Complete(_classBuilder.Type); }
private void GeneratePropertyCode(MethodArgILCodeVariable graphVariable, SerializableProperty target) { var extPropertyType = target.Ext; var argsField = _context.GetArgsField(target); var argsFieldVariable = _il.Var.Field(_il.Var.This(), argsField); if (extPropertyType.IsValueOrNullableOfValue()) { var isNullable = extPropertyType.Class == TypeClass.Nullable; var isEnum = extPropertyType.IsEnum(); var isValueType = extPropertyType.Ref.IsValueType; var mediatorPropertyType = isEnum ? extPropertyType.GetUnderlyingEnumType() : extPropertyType.Ref; var valueType = !isNullable && isValueType ? Members.Nullable[mediatorPropertyType].NullableType : mediatorPropertyType; var valueLocal = _il.DeclareLocal("value", valueType); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[valueType], argsFieldVariable, valueLocal); if (isValueType && !isNullable) { var labelValueNotFound = _il.DefineLabel(); _il.TransferLongIfFalse(labelValueNotFound); _il.Snippets.InvokeMethod(valueLocal, Members.Nullable[mediatorPropertyType].GetHasValue); _il.Negate(); var nullableHasValueLabel = _il.DefineLabel(); _il.TransferLong(nullableHasValueLabel); _il.MarkLabel(labelValueNotFound); _il.LoadValue(true); _il.MarkLabel(nullableHasValueLabel); } else { _il.Negate(); } var skipSetValueLabel = _il.DefineLabel(); _il.TransferLongIfTrue(skipSetValueLabel); var valueToAdd = (isValueType && !isNullable) ? new CallMethodILCode(valueLocal, Members.Nullable[mediatorPropertyType].GetValue) : (ILCodeParameter)valueLocal; _il.Snippets.SetPropertyValue(graphVariable, target.Ref, valueToAdd); _il.MarkLabel(skipSetValueLabel); } else if (extPropertyType.Class == TypeClass.Dictionary) { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisit, argsFieldVariable); var stateLocal = _il.DeclareLocal("state", typeof(ValueState)); _il.Var.Set(stateLocal); _il.Snippets.AreEqual(stateLocal, (int)ValueState.NotFound); var endLabel = _il.DefineLabel(); _il.TransferLongIfTrue(endLabel); _il.Snippets.AreEqual(stateLocal, (int)ValueState.Found); var nullLabel = _il.DefineLabel(); _il.TransferLongIfFalse(nullLabel); var dictionaryLocal = GenerateDictionaryEnumerateCode(target.Ref.PropertyType, target.Ref.Name); _il.Snippets.SetPropertyValue(graphVariable, target.Ref, dictionaryLocal.Cast(target.Ref.PropertyType)); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, argsFieldVariable); _il.TransferLong(endLabel); _il.MarkLabel(nullLabel); _il.Snippets.SetPropertyValue(graphVariable, target.Ref, null); _il.MarkLabel(endLabel); } else if (extPropertyType.Class == TypeClass.Collection) { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisit, argsFieldVariable); var stateLocal = _il.DeclareLocal("state", typeof(ValueState)); _il.Var.Set(stateLocal); _il.Snippets.AreEqual(stateLocal, (int)ValueState.NotFound); var endLabel = _il.DefineLabel(); _il.TransferLongIfTrue(endLabel); _il.Snippets.AreEqual(stateLocal, (int)ValueState.Found); var nullLabel = _il.DefineLabel(); _il.TransferLongIfFalse(nullLabel); var collectionParam = GenerateCollectionContent(extPropertyType, target.Ref.Name); _il.Snippets.SetPropertyValue(graphVariable, target.Ref, collectionParam); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, argsFieldVariable); _il.TransferLong(endLabel); _il.MarkLabel(nullLabel); _il.Snippets.SetPropertyValue(graphVariable, target.Ref, null); _il.MarkLabel(endLabel); } else { _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorTryVisit, argsFieldVariable); var stateLocal = _il.DeclareLocal("state", typeof(ValueState)); _il.Var.Set(stateLocal); _il.IfNotEqual(stateLocal, (int)ValueState.NotFound) .Then(() => { _il.IfEqual(stateLocal, (int)ValueState.Found) .Then(() => { var singleLocal = _il.DeclareLocal("single", extPropertyType.Ref); GenerateCreateAndChildCallCode(singleLocal); _il.Snippets.SetPropertyValue(graphVariable, target.Ref, singleLocal); _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, argsFieldVariable); }).Else(() => { _il.Snippets.SetPropertyValue(graphVariable, target.Ref, null); }).End(); }).End(); } }