protected void HandleTypeAttribute(XmlReader reader) { DebugCheck.NotNull(reader); string type; if (!Utils.GetString(Schema, reader, out type)) { return; } TypeModifier typeModifier; Function.RemoveTypeModifier(ref type, out typeModifier, out _isRefType); switch (typeModifier) { case TypeModifier.Array: _collectionKind = CollectionKind.Bag; break; default: Debug.Assert( typeModifier == TypeModifier.None, string.Format( CultureInfo.CurrentCulture, "Type is not valid for property {0}: {1}. The modifier for the type cannot be used in this context.", FQName, reader.Value)); break; } if (!Utils.ValidateDottedName(Schema, reader, type)) { return; } _unresolvedType = type; }
public CollectionTraits( CollectionKind type, MethodInfo addMethod, MethodInfo getEnumeratorMethod, PropertyInfo countProperty, Type elementType ) { this.CollectionType = type; this.GetEnumeratorMethod = getEnumeratorMethod; this.AddMethod = addMethod; this.CountProperty = countProperty; this.ElementType = elementType; }
internal static string GetTypeNameForErrorMessage(SchemaType type, CollectionKind colKind, bool isRef) { string typeName = type.FQName; if (isRef) { typeName = "Ref(" + typeName + ")"; } switch (colKind) { case CollectionKind.Bag: typeName = "Collection(" + typeName + ")"; break; default: Debug.Assert(colKind == CollectionKind.None, "Unexpected CollectionKind"); break; } return typeName; }
/** * @param kind The kind to set. */ public void setKind(CollectionKind kind) { this.kind = kind; }
public CollectionTypeReference(CollectionKind kind, TypeReference elementType) { Kind = kind; ElementType = elementType ?? throw new ArgumentNullException(nameof(elementType)); }
void WriteCollection(CollectionDataContract collectionContract) { XmlDictionaryString itemNamespace = dataContract.Namespace; XmlDictionaryString itemName = collectionDataContract.CollectionItemName; if (collectionContract.ChildElementNamespace != null) { writer.WriteNamespaceDecl(collectionDataContract.ChildElementNamespace); } if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; int i; // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (objLocal.GetType().GetElementType() != itemType) { throw new InvalidCastException(string.Format("Cannot cast array of {0} to array of {1}", objLocal.GetType().GetElementType(), itemType)); } ctx.IncrementArrayCount(writer, (Array)objLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName, itemNamespace)) { var arr = (Array)objLocal; var idx = new int [1]; for (i = 0; i < arr.Length; i++) { if (!TryWritePrimitive(itemType, null, null, i, itemNamespace, itemName, 0)) { WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0); idx [0] = i; var mbrVal = arr.GetValue(idx); WriteValue(itemType, mbrVal, false); WriteEndElement(); } } } } else { // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (!collectionContract.UnderlyingType.IsAssignableFrom(objLocal.GetType())) { throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", objLocal.GetType(), collectionContract.UnderlyingType)); } MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { incrementCollectionCountMethod.Invoke(ctx, new object [] { writer, objLocal }); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type [] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) { moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod; } if (getCurrentMethod == null) { getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod; } } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) { moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); } if (getCurrentMethod == null) { getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } } Type elementType = getCurrentMethod.ReturnType; object currentValue = null; // of elementType var enumerator = (IEnumerator)collectionContract.GetEnumeratorMethod.Invoke(objLocal, new object [0]); if (isDictionary) { enumerator = new CollectionDataContract.DictionaryEnumerator((IDictionaryEnumerator)enumerator); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null); enumerator = (IEnumerator)Activator.CreateInstance(enumeratorType, new object [] { enumerator }); } var emptyArray = new object [0]; while (enumerator != null && enumerator.MoveNext()) { currentValue = getCurrentMethod.Invoke(enumerator, emptyArray); if (incrementCollectionCountMethod == null) { XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke(ctx, new object [] { 1 }); } if (!TryWritePrimitive(elementType, () => currentValue, null, null, itemNamespace, itemName, 0)) { WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0); if (isGenericDictionary || isDictionary) { collectionDataContract.ItemContract.WriteXmlValue(writer, currentValue, ctx); } else { WriteValue(elementType, currentValue, false); } WriteEndElement(); } } } }
private bool ReturnTypeMeetsFunctionImportBasicRequirements(SchemaType type, CollectionKind returnTypeCollectionKind) { if (type is ScalarType && returnTypeCollectionKind == CollectionKind.Bag) return true; if (type is SchemaEntityType && returnTypeCollectionKind == CollectionKind.Bag) return true; if (Schema.SchemaVersion == XmlConstants.EdmVersionForV1_1) { if (type is ScalarType && returnTypeCollectionKind == CollectionKind.None) return true; if (type is SchemaEntityType && returnTypeCollectionKind == CollectionKind.None) return true; if (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.None) return true; if (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.Bag) return true; } if (Schema.SchemaVersion >= XmlConstants.EdmVersionForV2) { if (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.Bag) return true; } if (Schema.SchemaVersion >= XmlConstants.EdmVersionForV3) { if (type is SchemaEnumType && returnTypeCollectionKind == CollectionKind.Bag) return true; } return false; }
/// <summary> /// Initializes a new instance of the CollectionKindAnnotation class. /// </summary> /// <param name="kind">The collection kind.</param> public CollectionKindAnnotation(CollectionKind kind) { this.CollectionKind = kind; }
/// <summary> /// Emit the property set statments to properly set a ComplexType. /// </summary> /// <param name="statements">The collection of statements that the set statements should be added to.</param> private void EmitComplexTypePropertySetStatements(CodeStatementCollection statements, CollectionKind collectionKind) { CodePropertySetValueReferenceExpression valueRef = new CodePropertySetValueReferenceExpression(); //Since collections are not supported by //the stack, we don't need to do anything special //like doing an Attach or Detatch like the way we do for complex types. if (collectionKind == CollectionKind.None) { // this.fieldName = SetValidValue( this.fieldName, value, _pifieldName); statements.Add( new CodeAssignStatement( FieldRef, new CodeMethodInvokeExpression( ThisRef, Utils.SetValidValueMethodName, FieldRef, valueRef, new CodePrimitiveExpression(PropertyName)))); // this._complexPropertyInitialized = true; statements.Add( new CodeAssignStatement( ComplexPropertyInitializedFieldRef, new CodePrimitiveExpression(true))); } else { // this.fieldName = value; statements.Add( new CodeAssignStatement( FieldRef, valueRef)); } }
private static TypeUsage GetFunctionTypeUsage( bool isModelFunction, System.Data.Entity.Core.SchemaObjectModel.Function somFunction, FacetEnabledSchemaElement somParameter, DbProviderManifest providerManifest, bool areConvertingForProviderManifest, System.Data.Entity.Core.SchemaObjectModel.SchemaType type, CollectionKind collectionKind, bool isRefType, Converter.ConversionCache convertedItemCache, Dictionary <SchemaElement, GlobalItem> newGlobalItems) { if (somParameter != null && areConvertingForProviderManifest && somParameter.HasUserDefinedFacets) { return(somParameter.TypeUsage); } if (type == null) { if (isModelFunction && somParameter != null && somParameter is Parameter) { ((Parameter)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return(somParameter.TypeUsage); } if (somParameter == null || !(somParameter is ReturnType)) { return((TypeUsage)null); } ((ReturnType)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return(somParameter.TypeUsage); } EdmType edmType; if (!areConvertingForProviderManifest) { ScalarType scalarType = type as ScalarType; if (scalarType != null) { if (isModelFunction && somParameter != null) { if (somParameter.TypeUsage == null) { somParameter.ValidateAndSetTypeUsage(scalarType); } return(somParameter.TypeUsage); } if (isModelFunction) { ModelFunction modelFunction = somFunction as ModelFunction; if (modelFunction.TypeUsage == null) { modelFunction.ValidateAndSetTypeUsage(scalarType); } return(modelFunction.TypeUsage); } if (somParameter != null && somParameter.HasUserDefinedFacets && somFunction.Schema.DataModel == SchemaDataModelOption.ProviderDataModel) { somParameter.ValidateAndSetTypeUsage(scalarType); return(somParameter.TypeUsage); } edmType = (EdmType)Converter.GetPrimitiveType(scalarType, providerManifest); } else { edmType = (EdmType)Converter.LoadSchemaElement(type, providerManifest, convertedItemCache, newGlobalItems); if (isModelFunction && type is SchemaEnumType) { if (somParameter != null) { somParameter.ValidateAndSetTypeUsage(edmType); return(somParameter.TypeUsage); } if (somFunction != null) { ModelFunction modelFunction = (ModelFunction)somFunction; modelFunction.ValidateAndSetTypeUsage(edmType); return(modelFunction.TypeUsage); } } } } else { edmType = !(type is TypeElement) ? (EdmType)(type as ScalarType).Type : (EdmType)(type as TypeElement).PrimitiveType; } TypeUsage typeUsage; if (collectionKind != CollectionKind.None) { typeUsage = convertedItemCache.GetCollectionTypeUsageWithNullFacets(edmType); } else { EntityType entityType = edmType as EntityType; typeUsage = entityType == null || !isRefType?convertedItemCache.GetTypeUsageWithNullFacets(edmType) : TypeUsage.Create((EdmType) new RefType(entityType)); } return(typeUsage); }
private void ValidateFunctionImportReturnType(SchemaElement owner, SchemaType returnType, CollectionKind returnTypeCollectionKind, EntityContainerEntitySet entitySet, bool entitySetPathDefined) { if (returnType != null && !ReturnTypeMeetsFunctionImportBasicRequirements(returnType, returnTypeCollectionKind)) { owner.AddError(ErrorCode.FunctionImportUnsupportedReturnType, EdmSchemaErrorSeverity.Error, owner, GetReturnTypeErrorMessage(Schema.SchemaVersion, this.Name) ); } ValidateFunctionImportReturnType(owner, returnType, entitySet, entitySetPathDefined); }
public CollectionType CreateCollection(CollectionKind kind, Classifier elementType, bool deferFullInitialization = false, List <CollectionType> deferredCollectionList = null) { CollectionType newType; var tupleCacheKey = new Tuple <Classifier, CollectionKind>(elementType, kind); if (collectionTypeCache.ContainsKey(tupleCacheKey)) { return(collectionTypeCache[tupleCacheKey]); } if (kind == CollectionKind.Collection) { newType = new CollectionType(TypeTable, elementType, Any); } else { CollectionType inheritFrom; // = CreateCollection(CollectionKind.Collection, elementType, deferFullInitialization, deferredCollectionList); switch (kind) { case CollectionKind.Bag: inheritFrom = CreateCollection(CollectionKind.Collection, elementType, deferFullInitialization, deferredCollectionList); newType = new BagType(TypeTable, elementType, inheritFrom); break; case CollectionKind.Collection: newType = null; System.Diagnostics.Debug.Fail("Hups."); break; case CollectionKind.OrderedSet: inheritFrom = CreateCollection(CollectionKind.Collection, elementType, deferFullInitialization, deferredCollectionList); newType = new OrderedSetType(TypeTable, elementType, inheritFrom); break; case CollectionKind.Sequence: inheritFrom = CreateCollection(CollectionKind.Collection, elementType, deferFullInitialization, deferredCollectionList); newType = new SequenceType(TypeTable, elementType, inheritFrom); break; case CollectionKind.Set: inheritFrom = CreateCollection(CollectionKind.Collection, elementType, deferFullInitialization, deferredCollectionList); newType = new SetType(TypeTable, elementType, inheritFrom); break; default: newType = null; System.Diagnostics.Debug.Fail("CreateCollectionType( ... ): missing case for CollectionKind."); break; } } newType.DeferredFullInitialization = deferFullInitialization; if (!deferFullInitialization) { PerformDeferredInitialization(newType); } else { deferredCollectionList.Add(newType); } TypeTable.RegisterType(newType); collectionTypeCache[tupleCacheKey] = newType; return(newType); }
void WriteCollection(CollectionDataContract collectionContract) { LocalBuilder itemNamespace = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemNamespace"); ilg.Load(dataContractArg); ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty); ilg.Store(itemNamespace); LocalBuilder itemName = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName"); ilg.Load(dataContractArg); ilg.LoadMember(XmlFormatGeneratorStatics.CollectionItemNameProperty); ilg.Store(itemName); if (collectionContract.ChildElementNamespace != null) { ilg.Load(xmlWriterArg); ilg.Load(dataContractArg); ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespaceProperty); ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod); } if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i"); ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, xmlWriterArg, objectLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, objectLocal, itemName, itemNamespace)) { ilg.For(i, 0, objectLocal); if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/)) { WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/); ilg.LoadArrayElement(objectLocal, i); LocalBuilder memberValue = ilg.DeclareLocal(itemType, "memberValue"); ilg.Stloc(memberValue); WriteValue(memberValue, false /*writeXsiType*/); WriteEndElement(); } ilg.EndFor(); } } else { MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { ilg.Call(contextArg, incrementCollectionCountMethod, xmlWriterArg, objectLocal); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type[] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) { moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod; } if (getCurrentMethod == null) { getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod; } } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) { moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); } if (getCurrentMethod == null) { getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } } Type elementType = getCurrentMethod.ReturnType; LocalBuilder currentValue = ilg.DeclareLocal(elementType, "currentValue"); LocalBuilder enumerator = ilg.DeclareLocal(enumeratorType, "enumerator"); ilg.Call(objectLocal, collectionContract.GetEnumeratorMethod); if (isDictionary) { ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator); ilg.New(XmlFormatGeneratorStatics.DictionaryEnumeratorCtor); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null); ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam); ilg.New(dictEnumCtor); } ilg.Stloc(enumerator); ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod); if (incrementCollectionCountMethod == null) { ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); } if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/)) { WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/); if (isGenericDictionary || isDictionary) { ilg.Call(dataContractArg, XmlFormatGeneratorStatics.GetItemContractMethod); ilg.Load(xmlWriterArg); ilg.Load(currentValue); ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject); ilg.Load(contextArg); ilg.Call(XmlFormatGeneratorStatics.WriteXmlValueMethod); } else { WriteValue(currentValue, false /*writeXsiType*/); } WriteEndElement(); } ilg.EndForEach(moveNextMethod); } }
void WriteCollection(CollectionDataContract collectionContract) { XmlDictionaryString itemName = context.CollectionItemName; if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; int i; // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (objLocal.GetType().GetElementType() != itemType) { throw new InvalidCastException(string.Format("Cannot cast array of {0} to array of {1}", objLocal.GetType().GetElementType(), itemType)); } context.IncrementArrayCount(writer, (Array)objLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName)) { WriteArrayAttribute(); var arr = (Array)objLocal; var idx = new int [1]; for (i = 0; i < arr.Length; i++) { if (!TryWritePrimitive(itemType, null, null, i, itemName, 0)) { WriteStartElement(itemName, 0); idx [0] = i; var mbrVal = arr.GetValue(idx); WriteValue(itemType, mbrVal); WriteEndElement(); } } } } else { // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (!collectionContract.UnderlyingType.IsAssignableFrom(objLocal.GetType())) { throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", objLocal.GetType(), collectionContract.UnderlyingType)); } MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { incrementCollectionCountMethod.Invoke(context, new object [] { writer, objLocal }); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type [] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) { moveNextMethod = JsonFormatGeneratorStatics.MoveNextMethod; } if (getCurrentMethod == null) { getCurrentMethod = JsonFormatGeneratorStatics.GetCurrentMethod; } } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) { moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); } if (getCurrentMethod == null) { getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } } Type elementType = getCurrentMethod.ReturnType; object currentValue = null; // of elementType var enumerator = (IEnumerator)collectionContract.GetEnumeratorMethod.Invoke(objLocal, new object [0]); if (isDictionary) { ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfIDictionaryEnumerator }, null); enumerator = (IEnumerator)dictEnumCtor.Invoke(new object [] { enumerator }); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null); enumerator = (IEnumerator)Activator.CreateInstance(enumeratorType, new object [] { enumerator }); } bool canWriteSimpleDictionary = isDictionary || isGenericDictionary; bool writeSimpleDictionary = canWriteSimpleDictionary && context.UseSimpleDictionaryFormat; PropertyInfo genericDictionaryKeyProperty = null, genericDictionaryValueProperty = null; if (canWriteSimpleDictionary) { Type genericDictionaryKeyValueType = Globals.TypeOfKeyValue.MakeGenericType(keyValueTypes); genericDictionaryKeyProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.KeyString); genericDictionaryValueProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.ValueString); } if (writeSimpleDictionary) { WriteObjectAttribute(); object key, value; var empty_args = new object [0]; while ((bool)moveNextMethod.Invoke(enumerator, empty_args)) { currentValue = getCurrentMethod.Invoke(enumerator, empty_args); key = CodeInterpreter.GetMember(genericDictionaryKeyProperty, currentValue); value = CodeInterpreter.GetMember(genericDictionaryValueProperty, currentValue); WriteStartElement(key, 0 /*nameIndex*/); WriteValue(genericDictionaryValueProperty.PropertyType, value); WriteEndElement(); } } else { WriteArrayAttribute(); var emptyArray = new object [0]; while (enumerator != null && enumerator.MoveNext()) { currentValue = getCurrentMethod.Invoke(enumerator, emptyArray); if (incrementCollectionCountMethod == null) { XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke(context, new object [] { 1 }); } if (!TryWritePrimitive(elementType, () => currentValue, null, null, itemName, 0)) { WriteStartElement(itemName, 0); if (isGenericDictionary || isDictionary) { var jc = JsonDataContract.GetJsonDataContract(XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract( collectionDataContract.ItemContract)); // FIXME: this TypeHandle might be wrong; there is no easy way to get Type for currentValue though. DataContractJsonSerializer.WriteJsonValue(jc, writer, currentValue, context, currentValue.GetType().TypeHandle); } else { WriteValue(elementType, currentValue); } WriteEndElement(); } } } } }
private bool ReturnTypeMeetsFunctionImportBasicRequirements( SchemaType type, CollectionKind returnTypeCollectionKind) { return(type is ScalarType && returnTypeCollectionKind == CollectionKind.Bag || type is SchemaEntityType && returnTypeCollectionKind == CollectionKind.Bag || this.Schema.SchemaVersion == 1.1 && (type is ScalarType && returnTypeCollectionKind == CollectionKind.None || type is SchemaEntityType && returnTypeCollectionKind == CollectionKind.None || (type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.None || type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.Bag)) || (this.Schema.SchemaVersion >= 2.0 && type is SchemaComplexType && returnTypeCollectionKind == CollectionKind.Bag || this.Schema.SchemaVersion >= 3.0 && type is SchemaEnumType && returnTypeCollectionKind == CollectionKind.Bag)); }
CollectionType CreateCollectionType(CollectionKind kind, Classifier type) { CollectionType collectionType = Library.CreateCollection(kind, type); return(collectionType); }
private void WriteCollection(CollectionDataContract collectionContract) { LocalBuilder itemName = _ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName"); _ilg.Load(_contextArg); _ilg.LoadMember(JsonFormatGeneratorStatics.CollectionItemNameProperty); _ilg.Store(itemName); if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, _xmlWriterArg, _objectLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, _objectLocal, itemName)) { WriteArrayAttribute(); _ilg.For(i, 0, _objectLocal); if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemName, 0 /*nameIndex*/)) { WriteStartElement(itemName, 0 /*nameIndex*/); _ilg.LoadArrayElement(_objectLocal, i); LocalBuilder memberValue = _ilg.DeclareLocal(itemType, "memberValue"); _ilg.Stloc(memberValue); WriteValue(memberValue); WriteEndElement(); } _ilg.EndFor(); } } else { MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { _ilg.Call(_contextArg, incrementCollectionCountMethod, _xmlWriterArg, _objectLocal); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type[] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty <Type>()); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty <Type>()); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) { moveNextMethod = JsonFormatGeneratorStatics.MoveNextMethod; } if (getCurrentMethod == null) { getCurrentMethod = JsonFormatGeneratorStatics.GetCurrentMethod; } } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) { moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); } if (getCurrentMethod == null) { getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } } Type elementType = getCurrentMethod.ReturnType; LocalBuilder currentValue = _ilg.DeclareLocal(elementType, "currentValue"); LocalBuilder enumerator = _ilg.DeclareLocal(enumeratorType, "enumerator"); _ilg.Call(_objectLocal, collectionContract.GetEnumeratorMethod); if (isDictionary) { ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, new Type[] { Globals.TypeOfIDictionaryEnumerator }); _ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator); _ilg.New(dictEnumCtor); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, new Type[] { ctorParam }); _ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam); _ilg.New(dictEnumCtor); } _ilg.Stloc(enumerator); bool canWriteSimpleDictionary = isDictionary || isGenericDictionary; if (canWriteSimpleDictionary) { Type genericDictionaryKeyValueType = Globals.TypeOfKeyValue.MakeGenericType(keyValueTypes); PropertyInfo genericDictionaryKeyProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.KeyString); PropertyInfo genericDictionaryValueProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.ValueString); _ilg.Load(_contextArg); _ilg.LoadMember(JsonFormatGeneratorStatics.UseSimpleDictionaryFormatWriteProperty); _ilg.If(); WriteObjectAttribute(); LocalBuilder pairKey = _ilg.DeclareLocal(Globals.TypeOfString, "key"); LocalBuilder pairValue = _ilg.DeclareLocal(keyValueTypes[1], "value"); _ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod); _ilg.LoadAddress(currentValue); _ilg.LoadMember(genericDictionaryKeyProperty); _ilg.ToString(keyValueTypes[0]); _ilg.Stloc(pairKey); _ilg.LoadAddress(currentValue); _ilg.LoadMember(genericDictionaryValueProperty); _ilg.Stloc(pairValue); WriteStartElement(pairKey, 0 /*nameIndex*/); WriteValue(pairValue); WriteEndElement(); _ilg.EndForEach(moveNextMethod); _ilg.Else(); } WriteArrayAttribute(); _ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod); if (incrementCollectionCountMethod == null) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); } if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemName, 0 /*nameIndex*/)) { WriteStartElement(itemName, 0 /*nameIndex*/); if (isGenericDictionary || isDictionary) { _ilg.Call(_dataContractArg, JsonFormatGeneratorStatics.GetItemContractMethod); _ilg.Call(JsonFormatGeneratorStatics.GetRevisedItemContractMethod); _ilg.Call(JsonFormatGeneratorStatics.GetJsonDataContractMethod); _ilg.Load(_xmlWriterArg); _ilg.Load(currentValue); _ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject); _ilg.Load(_contextArg); _ilg.Load(currentValue.LocalType); _ilg.LoadMember(JsonFormatGeneratorStatics.TypeHandleProperty); _ilg.Call(JsonFormatGeneratorStatics.WriteJsonValueMethod); } else { WriteValue(currentValue); } WriteEndElement(); } _ilg.EndForEach(moveNextMethod); if (canWriteSimpleDictionary) { _ilg.EndIf(); } } }
public PropertyTypeReferences(TypeReference typeReference, PrimitiveType primitiveType, CollectionKind collectionKind) { Type type = primitiveType.ClrEquivalentType; if (collectionKind == CollectionKind.None) { _nonNullable = typeReference.ForType(type); if (type.IsValueType) { _nullable = typeReference.NullableForType(type); } else { _nullable = typeReference.ForType(type); } } else { CodeTypeReference primitiveTypeRef = typeReference.ForType(type); CodeTypeReference collectionType = GetCollectionTypeReference(typeReference, primitiveTypeRef, collectionKind); _nonNullable = collectionType; _nullable = collectionType; } }
public PropertyTypeReferences(TypeReference typeReference, ComplexType complexType, CollectionKind collectionKind, ClientApiGenerator generator) { CodeTypeReference baseType = generator.GetLeastPossibleQualifiedTypeReference(complexType); baseType = GetCollectionTypeReference(typeReference, baseType, collectionKind); _nonNullable = baseType; _nullable = baseType; }
private static TypeUsage GetFunctionTypeUsage( bool isModelFunction, Som.Function somFunction, Som.FacetEnabledSchemaElement somParameter, DbProviderManifest providerManifest, bool areConvertingForProviderManifest, Som.SchemaType type, CollectionKind collectionKind, bool isRefType, ConversionCache convertedItemCache, Dictionary<Som.SchemaElement, GlobalItem> newGlobalItems) { if (null != somParameter && areConvertingForProviderManifest && somParameter.HasUserDefinedFacets) { return somParameter.TypeUsage; } if (null == type) { if (isModelFunction && somParameter != null && somParameter is Som.Parameter) { ((Som.Parameter)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return somParameter.TypeUsage; } else if (somParameter != null && somParameter is Som.ReturnType) { ((Som.ReturnType)somParameter).ResolveNestedTypeNames(convertedItemCache, newGlobalItems); return somParameter.TypeUsage; } else { return null; } } EdmType edmType; if (!areConvertingForProviderManifest) { // SOM verifies the type is either scalar, row, or entity var scalarType = type as Som.ScalarType; if (null != scalarType) { if (isModelFunction && somParameter != null) { if (somParameter.TypeUsage == null) { somParameter.ValidateAndSetTypeUsage(scalarType); } return somParameter.TypeUsage; } else if (isModelFunction) { var modelFunction = somFunction as Som.ModelFunction; if (modelFunction.TypeUsage == null) { modelFunction.ValidateAndSetTypeUsage(scalarType); } return modelFunction.TypeUsage; } else if (somParameter != null && somParameter.HasUserDefinedFacets && somFunction.Schema.DataModel == Som.SchemaDataModelOption.ProviderDataModel) { somParameter.ValidateAndSetTypeUsage(scalarType); return somParameter.TypeUsage; } else { edmType = GetPrimitiveType(scalarType, providerManifest); } } else { edmType = (EdmType)LoadSchemaElement( type, providerManifest, convertedItemCache, newGlobalItems); // Neither FunctionImport nor its Parameters can have facets when defined in CSDL so for enums, // since they are only a CSpace concept, we need to process facets only on model functions if (isModelFunction && type is Som.SchemaEnumType) { Debug.Assert(somFunction.Schema.DataModel == Som.SchemaDataModelOption.EntityDataModel, "Enums live only in CSpace"); if (somParameter != null) { somParameter.ValidateAndSetTypeUsage(edmType); return somParameter.TypeUsage; } else if (somFunction != null) { var modelFunction = ((Som.ModelFunction)somFunction); modelFunction.ValidateAndSetTypeUsage(edmType); return modelFunction.TypeUsage; } else { Debug.Fail("Should never get here."); } } } } else if (type is Som.TypeElement) { var typeElement = type as Som.TypeElement; edmType = typeElement.PrimitiveType; } else { var typeElement = type as Som.ScalarType; edmType = typeElement.Type; } //Construct type usage TypeUsage usage; if (collectionKind != CollectionKind.None) { usage = convertedItemCache.GetCollectionTypeUsageWithNullFacets(edmType); } else { var entityType = edmType as EntityType; if (entityType != null && isRefType) { usage = TypeUsage.Create(new RefType(entityType)); } else { usage = convertedItemCache.GetTypeUsageWithNullFacets(edmType); } } return usage; }
private static CodeTypeReference GetCollectionTypeReference(TypeReference typeReference, CodeTypeReference baseType, CollectionKind collectionKind) { if (collectionKind == CollectionKind.Bag) { baseType = GetCollectionTypeReferenceForBagSemantics(typeReference, baseType); } else if (collectionKind == CollectionKind.List) { baseType = GetCollectionTypeReferenceForListSemantics(typeReference, baseType); } else { Debug.Assert(collectionKind == CollectionKind.None, "Was another CollectionKind value added"); // nothing more to do for .None } return(baseType); }
public void ShouldSerialize(CollectionKind kind, string expected) { string actual = JsonConvert.SerializeObject(kind); Assert.Equal(expected, actual, ignoreLineEndingDifferences: true); }
public void ShouldDeserialize(string kind, CollectionKind expected) { CollectionKind actual = JsonConvert.DeserializeObject <CollectionKind>(kind); Assert.Equal(expected, actual); }
/// <summary> /// Handles the Multiplicity attribute on the property. /// </summary> /// <param name="reader"></param> private void HandleCollectionKindAttribute(XmlReader reader) { string value = reader.Value; if (value == XmlConstants.CollectionKind_None) { _collectionKind = CollectionKind.None; } else { if (value == XmlConstants.CollectionKind_List) { _collectionKind = CollectionKind.List; } else if (value == XmlConstants.CollectionKind_Bag) { _collectionKind = CollectionKind.Bag; } else { Debug.Fail("Xsd should have changed", "XSD validation should have ensured that" + " Multiplicity attribute has only 'None' or 'Bag' or 'List' as the values"); return; } } }