コード例 #1
0
 public void BuildTravelReadMethod()
 {
     var graphArgument = new MethodArgILCodeVariable(2, _target.Type);
     foreach (var property in _target.Properties) {
         GeneratePropertyCode(graphArgument, property);
     }
     _il.Return();
 }
コード例 #2
0
        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);
        }
コード例 #3
0
        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();
            }
        }