예제 #1
0
        public CollectionMembers(ExtendedType collectionType)
        {
            ArrayContainerTypeInfo arrayTypeInfo;
            if (collectionType.TryGetArrayTypeInfo(out arrayTypeInfo)) {
                if (arrayTypeInfo.Ranks > 3)
                    throw new NotSupportedException("The serialization engine is limited to 3 ranks in arrays");
                if (arrayTypeInfo.Ranks == 3) {
                    var baseType = typeof (ICollection<>);
                    ElementType = baseType.MakeGenericType(baseType.MakeGenericType(arrayTypeInfo.ElementType));
                    ToArray = typeof (ArrayProvider).GetMethod("To3DArray").MakeGenericMethod(arrayTypeInfo.ElementType);
                }
                else if (arrayTypeInfo.Ranks == 2) {
                    ElementType = typeof (ICollection<>).MakeGenericType(arrayTypeInfo.ElementType);
                    ToArray = typeof(ArrayProvider).GetMethod("To2DArray").MakeGenericMethod(arrayTypeInfo.ElementType);
                }
                else {
                    ElementType = arrayTypeInfo.ElementType;
                    ToArray = typeof(ArrayProvider).GetMethod("ToArray").MakeGenericMethod(arrayTypeInfo.ElementType);
                }
            }
            else {
                ElementType = collectionType.Container.AsCollection().ElementType;
            }

            ElementTypeExt = ElementType.Extend();
            VariableType = typeof (ICollection<>).MakeGenericType(ElementType);

            Add = VariableType.GetMethod("Add", new[] { ElementType });
            var instanceType = collectionType.Ref.IsInterface || collectionType.Ref.IsArray
                ? typeof(List<>).MakeGenericType(ElementType)
                : collectionType.Ref;

            Constructor = instanceType.GetConstructor(Type.EmptyTypes);
            if (Constructor == null) throw InvalidGraphException.NoParameterLessConstructor(collectionType.Ref);
        }
        private void GenerateEnumerateCollectionContentCode(ExtendedType target, ILCodeParameter collectionParameter)
        {
            ArrayContainerTypeInfo arrayTypeInfo;
            if (target.TryGetArrayTypeInfo(out arrayTypeInfo) && arrayTypeInfo.Ranks > 1) {
                if (arrayTypeInfo.Ranks > 3)
                    throw new NotSupportedException("The serialization engine is limited to 3 ranks in arrays");

                _il.Snippets.ForLoop(0, new CallMethodILCode(collectionParameter, Members.ArrayGetLength, 0), 1,
                    r0 => {
                        _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, collectionParameter, Members.VisitArgsCollectionInCollection);
                        _il.Snippets.ForLoop(0, new CallMethodILCode(collectionParameter, Members.ArrayGetLength, 1), 1,
                            r1 => {
                                if (arrayTypeInfo.Ranks > 2) {
                                    _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorVisit, collectionParameter, Members.VisitArgsCollectionInCollection);

                                    _il.Snippets.ForLoop(0, new CallMethodILCode(collectionParameter, Members.ArrayGetLength, 1), 1,
                                        r2 => GenerateEnumerateContentCode(
                                            new CallMethodILCode(collectionParameter, target.Ref.GetMethod("Get"), r0, r1, r2),
                                            LevelType.CollectionItem));

                                    _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, collectionParameter, Members.VisitArgsCollectionInCollection);
                                }
                                else {
                                    GenerateEnumerateContentCode(new CallMethodILCode(collectionParameter, target.Ref.GetMethod("Get"), r0, r1), LevelType.CollectionItem);
                                }
                            });
                        _il.Snippets.InvokeMethod(_visitorVariable, Members.VisitorLeave, collectionParameter, Members.VisitArgsCollectionInCollection);
                    });
            }
            else {
                var part = new ILEnumerateCode(collectionParameter, (il, it) => GenerateEnumerateContentCode(it, LevelType.CollectionItem));
                _il.Generate(part);
            }
        }