コード例 #1
0
        public void BuildTraveller()
        {
            if (_classBuilder.IsSealed)
            {
                throw new InvalidOperationException("Classification builder is sealed");
            }
            var target          = _typeProvider.GetOrCreate(_type);
            var members         = _dtContext.Members;
            var factoryArgument = new ILArgPointer(members.VisitArgsFactoryType, 1);


            var childTravellers = new Dictionary <Type, ChildTravellerInfo>();
            var argFields       = new Dictionary <SerializableProperty, FieldInfo>();

            var il             = _constructorBuilder.IL;
            var travellerIndex = 0;

            foreach (var property in target.Properties)
            {
                var argField      = _classBuilder.DefinePrivateField("_arg" + property.Ref.Name, members.VisitArgsType);
                var visitArgsCode = new ILCallMethodSnippet(factoryArgument, members.ConstructVisitArgsMethod, property.Ref.Name);
                il.Set(ILPointer.This(), argField, visitArgsCode);
                argFields.Add(property, argField);

                if (!ReflectionAnalyzer.TryGetComplexTypes(property.Ext, out var 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 = ILSnippet.Call(factoryArgument, members.ConstructVisitArgsWithTypeMethod, type);
                    var newTraveller   = ILPointer.New(dynamicTraveller.Constructor, getFactoryCode);
                    il.Set(ILPointer.This(), fieldBuilder, newTraveller);
                }
            }
            il.Emit(OpCodes.Ret);

            var context = new TravellerContext(childTravellers, argFields);

            BuildWriteMethods(target, context);
            BuildReadMethods(target, context);

            _classBuilder.Seal();
            DynamicTraveller.Complete(_classBuilder.Type);
        }
コード例 #2
0
        private ILLocalVariable GenerateDictionaryEnumerateCode(Type type, string refName)
        {
            var extType           = _typeProvider.Extend(type);
            var dictionaryMembers = new DictionaryMembers(extType);

            var local = _il.NewLocal(dictionaryMembers.VariableType);

            _il.Construct(dictionaryMembers.Constructor);
            _il.Set(local);

            var keyType = Members.Nullable.TryGetValue(dictionaryMembers.KeyType, out var keyNullableMembers)
                ? keyNullableMembers.NullableType
                : dictionaryMembers.KeyType;

            var conditionLabel = _il.NewLabel();
            var bodyLabel      = _il.NewLabel();

            var keyTypeExt = _typeProvider.Extend(keyType);

            // First of all, transfer to the condition part
            conditionLabel.TransferLong();

            // Mark that we enter the body of the loop
            bodyLabel.Mark();
            ILPointer keyParam;

            if (keyTypeExt.IsValueOrNullableOfValue())
            {
                keyParam = _il.NewLocal(keyType);
            }
            else if (keyTypeExt.Classification == TypeClassification.Dictionary)
            {
                keyParam = GenerateDictionaryEnumerateCode(keyType, refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryKey);
            }
            else if (keyTypeExt.Classification == TypeClassification.Collection)
            {
                keyParam = GenerateCollectionContent(keyTypeExt, refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryKey);
            }
            else
            {
                var keyLocal = _il.NewLocal(keyType);
                GenerateCreateAndChildCallCode(keyLocal);
                keyParam = keyLocal;
                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryKey);
            }

            var throwExceptionLabel = _il.NewLabel();

            var hasNullableMembers = Members.Nullable.TryGetValue(
                dictionaryMembers.ValueType, out var valueNullableMembers);
            var valueType    = dictionaryMembers.ValueType;
            var extValueType = _typeProvider.Extend(valueType);

            ILPointer valueParam;

            if (extValueType.IsValueOrNullableOfValue())
            {
                var loadTrueLabel     = _il.NewLabel();
                var checkIfErrorLabel = _il.NewLabel();

                valueParam = _il.NewLocal(hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType);
                _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[dictionaryMembers.ValueType], Members.VisitArgsDictionaryValue, valueParam);
                loadTrueLabel.TransferLongIfFalse();

                if (hasNullableMembers)
                {
                    _il.InvokeMethod(valueParam, valueNullableMembers.GetHasValue);
                    _il.Negate();
                }
                else
                {
                    _il.AreEqual(valueParam, null);
                }
                checkIfErrorLabel.TransferLong();
                loadTrueLabel.Mark();
                _il.Load(true);
                checkIfErrorLabel.Mark();
                throwExceptionLabel.TransferLongIfTrue();
            }
            else if (extValueType.Classification == TypeClassification.Dictionary)
            {
                var callTryVisitValue = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryValue);
                _il.AreEqual(callTryVisitValue, (int)ValueState.Found);
                throwExceptionLabel.TransferLongIfFalse();

                valueParam = GenerateDictionaryEnumerateCode(valueType, refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInDictionaryValue);
            }
            else if (extValueType.Classification == TypeClassification.Collection)
            {
                var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryValue);
                _il.AreEqual(callTryVisit, (int)ValueState.Found);
                throwExceptionLabel.TransferLongIfFalse();

                valueParam = GenerateCollectionContent(_typeProvider.Extend(valueType), refName);

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInDictionaryValue);
            }
            else
            {
                var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryValue);
                _il.AreEqual(callTryVisit, (int)ValueState.Found);
                throwExceptionLabel.TransferLongIfFalse();

                var valueLocal = _il.NewLocal(hasNullableMembers ? valueNullableMembers.NullableType : dictionaryMembers.ValueType);
                GenerateCreateAndChildCallCode(valueLocal);
                valueParam = valueLocal;

                _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryValue);
            }

            _il.Load(local);
            GenerateLoadParamValueCode(keyParam);
            GenerateLoadParamValueCode(valueParam);

            _il.EmitCall(OpCodes.Callvirt, dictionaryMembers.Add, null);
            conditionLabel.TransferLong();

            throwExceptionLabel.Mark();
            _il.Throw(new ILCallMethodSnippet(Members.ExceptionNoDictionaryValue, refName));

            conditionLabel.Mark();

            if (keyTypeExt.IsValueOrNullableOfValue())
            {
                var loadZeroLabel       = _il.NewLabel();
                var checkConditionLabel = _il.NewLabel();

                _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[keyType], Members.VisitArgsDictionaryKey, keyParam);
                loadZeroLabel.TransferLongIfFalse();

                if (keyTypeExt.Info.IsValueType)
                {
                    _il.InvokeMethod(keyParam, Members.Nullable[keyType].GetHasValue);
                    checkConditionLabel.TransferLong();
                }
                else
                {
                    _il.AreEqual(keyParam, ILPointer.Null);
                    _il.Negate();
                    checkConditionLabel.TransferLong();
                }

                loadZeroLabel.Mark();
                _il.Load(false);
                checkConditionLabel.Mark();
                bodyLabel.TransferLongIfTrue();
            }
            else if (keyTypeExt.Classification == TypeClassification.Dictionary)
            {
                var callTryVisitKey = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInDictionaryKey);
                _il.AreEqual(callTryVisitKey, (int)ValueState.Found);
                bodyLabel.TransferLongIfTrue();
            }
            else if (keyTypeExt.Classification == TypeClassification.Collection)
            {
                var callTryVisitKey = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInDictionaryKey);
                _il.AreEqual(callTryVisitKey, (int)ValueState.Found);
                bodyLabel.TransferLongIfTrue();
            }
            else
            {
                var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryKey);
                _il.AreEqual(callTryVisit, (int)ValueState.Found);
                bodyLabel.TransferLongIfTrue();
            }

            return(local);
        }
コード例 #3
0
        private ILPointer GenerateCollectionContent(ExtendedType target, string refName)
        {
            var collectionMembers = new CollectionMembers(target);
            var isValueType       = collectionMembers.ElementType.GetTypeInfo().IsValueType;

            var collectionLocal = _il.NewLocal(collectionMembers.VariableType);
            var collection      = ILPointer.New(collectionMembers.Constructor)
                                  .Cast(collectionMembers.VariableType);

            _il.Set(collectionLocal, collection);

            var valueLocal = DeclareCollectionItemLocal(collectionMembers.ElementType);;

            if (collectionMembers.ElementTypeExt.IsValueOrNullableOfValue())
            {
                _il.WhileLoop(il => { // While condition
                    _il.InvokeMethod(_visitorVariable, Members.VisitorTryVisitValue[collectionMembers.ElementType], Members.VisitArgsCollectionItem, valueLocal);

                    var valueNotFoundLabel = _il.NewLabel();
                    valueNotFoundLabel.TransferLongIfFalse();

                    if (isValueType)
                    {
                        _il.InvokeMethod(valueLocal, Members.Nullable[collectionMembers.ElementType].GetHasValue);
                    }
                    else
                    {
                        _il.AreEqual(valueLocal, ILPointer.Null);
                        _il.Negate();
                    }

                    var isNullLabel = _il.NewLabel();
                    isNullLabel.TransferLong();

                    valueNotFoundLabel.Mark();
                    _il.Load(0);
                    isNullLabel.Mark();
                }, il => {
                    _il.Load(collectionLocal);

                    GenerateLoadParamValueCode(valueLocal);

                    _il.EmitCall(OpCodes.Callvirt, collectionMembers.Add, null);
                });
            }
            else if (collectionMembers.ElementTypeExt.Classification == TypeClassification.Dictionary)
            {
                _il.WhileLoop(il => { // Condition
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsDictionaryInCollection);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateDictionaryEnumerateCode(collectionMembers.ElementType, refName);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsDictionaryInCollection);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else if (collectionMembers.ElementTypeExt.Classification == TypeClassification.Collection)
            {
                _il.WhileLoop(il => { // Condition
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionInCollection);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    var contentParam = GenerateCollectionContent(collectionMembers.ElementTypeExt, refName);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionInCollection);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, contentParam);
                });
            }
            else
            {
                _il.WhileLoop(il => {
                    var callTryVisit = new ILCallMethodSnippet(_visitorVariable, Members.VisitorTryVisit, Members.VisitArgsCollectionItem);
                    _il.AreEqual(callTryVisit, (int)ValueState.Found);
                }, il => {
                    GenerateCreateAndChildCallCode(valueLocal);
                    _il.InvokeMethod(_visitorVariable, Members.VisitorLeave, Members.VisitArgsCollectionItem);
                    _il.InvokeMethod(collectionLocal, collectionMembers.Add, valueLocal);
                });
            }
            if (target.Ref.IsArray)
            {
                return(new ILCallMethodSnippet(collectionMembers.ToArray, collectionLocal));
            }

            return(collectionLocal);
        }