/// <summary> /// Constructor for <c>ClassDescriptor</c> takes /// <c>Type</c> as the input parameter. Initializes /// internal variables and resovles the tagName for /// class. /// </summary> /// <param name="thatClass"> /// <c>Type</c> of the class defined by this /// <c>ClassDescriptor</c> /// </param> public ClassDescriptor(Type thatClass) : base(XmlTools.GetXmlTagName(thatClass, SimplTypesScope.STATE), thatClass.Name) { _describedClass = thatClass; _describedClassSimpleName = thatClass.Name; _describedClassPackageName = thatClass.Namespace; //generics if (thatClass.GetTypeInfo().IsGenericType) { int index = _describedClassSimpleName.IndexOf('`'); String simpleName = _describedClassSimpleName.Substring(0, index); name = simpleName; _describedClassSimpleName = simpleName; index = _tagName.IndexOf('`'); if (index != -1) { String tagName = _tagName.Substring(0, index); this._tagName = tagName; } } if (XmlTools.IsAnnotationPresent <SimplUseEqualsEquals>(thatClass)) { _strictObjectGraphRequired = true; } SimplDescriptorClasses descriptorsClassesAttribute = XmlTools.GetAnnotation <SimplDescriptorClasses>(thatClass); if (descriptorsClassesAttribute != null) { classDescriptorClass = descriptorsClassesAttribute.Classes[0]; fieldDescriptorClass = descriptorsClassesAttribute.Classes[1]; } if (XmlTools.IsAnnotationPresent(thatClass, typeof(SimplInherit))) { this.SuperClass = GetClassDescriptor(thatClass.GetTypeInfo().BaseType); } //generics AddGenericTypeVariables(); }
/// <summary> /// Recursive method to resolve annotations in parameter class and its super classes. /// This mehthod creates field descriptors and other optimized datastructures, which /// is used for marshalling and ummarshalling of runtime objects. /// </summary> /// <param name="thatClass"> /// The parameter class <c>Type</c> to resolve any defined annotations. /// </param> /// <param name="fieldDescriptorClass"> /// Used by recursive call from inside the function. Can be null if being called /// for the first time. /// </param> public void DeriveAndOrganizeFieldsRecursive(Type thatClass) { if (XmlTools.IsAnnotationPresent <SimplInherit>(thatClass)) { TypeInfo classTypeInfo = thatClass.GetTypeInfo(); Type[] superClassGenericArguments = classTypeInfo.BaseType.GenericTypeArguments; ClassDescriptor superClassDescriptor = GetClassDescriptor(classTypeInfo.BaseType); ReferFieldDescriptorsFrom(superClassDescriptor, superClassGenericArguments); } IEnumerable <FieldInfo> fields = thatClass.GetTypeInfo().DeclaredFields; // Iterate through all fields for the type foreach (FieldInfo thatField in fields) { // We don't serialize static values in S.im.pl, continue on to the next field if ((thatField.IsStatic)) { continue; } Int16 fieldType = FieldTypes.UnsetType; if (XmlTools.IsScalar(thatField)) { fieldType = FieldTypes.Scalar; } else if (XmlTools.IsAnnotationPresent <SimplComposite>(thatField)) { fieldType = FieldTypes.CompositeElement; } else if (XmlTools.IsAnnotationPresent <SimplCollection>(thatField)) { fieldType = FieldTypes.CollectionElement; } else if (XmlTools.IsAnnotationPresent <SimplMap>(thatField)) { fieldType = FieldTypes.MapElement; } if (fieldType == FieldTypes.UnsetType) { continue; //not a simpl serialization annotated field } FieldDescriptor fieldDescriptor = NewFieldDescriptor(thatField, fieldType, fieldDescriptorClass); //generics fieldDescriptor.GenericTypeVarsContextCD = this; if (fieldDescriptor.FdType == FieldTypes.Scalar) { Hint xmlHint = fieldDescriptor.XmlHint; switch (xmlHint) { case Hint.XmlAttribute: _attributeFieldDescriptors.Add(fieldDescriptor); break; case Hint.XmlText: case Hint.XmlTextCdata: break; case Hint.XmlLeaf: case Hint.XmlLeafCdata: _elementFieldDescriptors.Add(fieldDescriptor); break; } } else { _elementFieldDescriptors.Add(fieldDescriptor); } if (XmlTools.IsCompositeAsScalarValue(thatField)) { _scalarValueFieldDescriptor = fieldDescriptor; } _fieldDescriptorsByFieldName.Add(thatField.Name, fieldDescriptor); if (fieldDescriptor.IsMarshallOnly) { continue; } String fieldTagName = fieldDescriptor.TagName; if (fieldDescriptor.IsWrapped) { FieldDescriptor wrapper = NewFieldDescriptor(fieldDescriptor, fieldTagName, fieldDescriptorClass); MapTagToFdForTranslateFrom(fieldTagName, wrapper); } else if (!fieldDescriptor.IsPolymorphic) { String tag = fieldDescriptor.IsCollection ? fieldDescriptor.CollectionOrMapTagName : fieldTagName; MapTagToFdForTranslateFrom(tag, fieldDescriptor); var otherTagsAttributes = XmlTools.GetAnnotation <SimplOtherTags>(thatField); String[] otherTags = XmlTools.OtherTags(otherTagsAttributes); if (otherTags != null) { foreach (String otherTag in otherTags) { MapTagToFdForTranslateFrom(otherTag, fieldDescriptor); } } } else { MapTagClassDescriptors(fieldDescriptor); } } }
private int DeriveNestedSerialization(FieldInfo thatField, int annotationType) { int result = annotationType; Type thatFieldType = thatField.FieldType; switch (annotationType) { case FieldTypes.CompositeElement: String compositeTag = XmlTools.GetAnnotation <SimplComposite>(thatField).TagName; Boolean isWrap = XmlTools.IsAnnotationPresent <SimplWrap>(thatField); Boolean compositeTagIsNullOrEmpty = String.IsNullOrEmpty(compositeTag); if (!IsPolymorphic) { if (isWrap && compositeTagIsNullOrEmpty) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate [SimplComposite] " + thatField.Name + " because its tag argument is missing."; Debug.WriteLine(msg); return(FieldTypes.IgnoredAttribute); } _elementClassDescriptor = ClassDescriptor.GetClassDescriptor(thatFieldType); _elementClass = _elementClassDescriptor.DescribedClass; compositeTag = XmlTools.GetXmlTagName(thatField); } else { if (!compositeTagIsNullOrEmpty) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate [SimplComposite] " + thatField.Name + " because its tag argument is missing."; Debug.WriteLine(msg); } } compositeTagName = compositeTag; break; case FieldTypes.CollectionElement: if (!(typeof(IList).GetTypeInfo().IsAssignableFrom(thatField.FieldType.GetTypeInfo()))) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate " + "[SimplCollection] " + field.Name + " because the annotated field is not an instance of " + typeof(IList).Name + "."; Debug.WriteLine(msg); return(FieldTypes.IgnoredAttribute); } String collectionTag = XmlTools.GetAnnotation <SimplCollection>(thatField).TagName; if (!IsPolymorphic) { Type collectionElementType = GetTypeArgs(thatField, 0); if (String.IsNullOrEmpty(collectionTag)) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate [SimplCollection]" + field.Name + " because its tag argument is missing."; Debug.WriteLine(msg); return(FieldTypes.IgnoredElement); } if (collectionElementType == null) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate [SimplCollection] " + field.Name + " because the parameterized type argument for the Collection is missing."; Debug.WriteLine(msg); return(FieldTypes.IgnoredElement); } if (!TypeRegistry.ScalarTypes.Contains(collectionElementType)) { _elementClassDescriptor = ClassDescriptor.GetClassDescriptor(collectionElementType); _elementClass = _elementClassDescriptor.DescribedClass; } else { result = FieldTypes.CollectionScalar; DeriveScalarSerialization(collectionElementType, field); if (ScalarType == null) { result = FieldTypes.IgnoredElement; String msg = "Can't identify ScalarType for serialization of " + collectionElementType; Debug.WriteLine(msg); } } } else { if (!String.IsNullOrEmpty(collectionTag)) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tIgnoring argument to [SimplCollection] " + field.Name + " because it is declared polymorphic with [SimplClasses]."; } } _collectionOrMapTagName = collectionTag; collectionType = TypeRegistry.GetCollectionType(thatField); break; case FieldTypes.MapElement: if (!(typeof(IDictionary).GetTypeInfo().IsAssignableFrom(thatField.FieldType.GetTypeInfo()))) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate " + "[SimplMap] " + field.Name + " because the annotated field is not an instance of " + typeof(IDictionary).Name + "."; Debug.WriteLine(msg); return(FieldTypes.IgnoredAttribute); } String mapTag = XmlTools.GetAnnotation <SimplMap>(thatField).TagName; if (!IsPolymorphic) { Type mapElementType = GetTypeArgs(thatField, 1); if (String.IsNullOrEmpty(mapTag)) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate [SimplMap]" + field.Name + " because its tag argument is missing."; Debug.WriteLine(msg); return(FieldTypes.IgnoredElement); } if (mapElementType == null) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tCan't translate [SimplMap] " + field.Name + " because the parameterized type argument for the map is missing."; Debug.WriteLine(msg); return(FieldTypes.IgnoredElement); } if (!TypeRegistry.ScalarTypes.Contains(mapElementType)) { _elementClassDescriptor = ClassDescriptor.GetClassDescriptor(mapElementType); _elementClass = _elementClassDescriptor.DescribedClass; } } else { if (!String.IsNullOrEmpty(mapTag)) { String msg = "In " + declaringClassDescriptor.DescribedClass + "\n\tIgnoring argument to [SimplMap] " + field.Name + " because it is declared polymorphic with [SimplClasses]."; } } _collectionOrMapTagName = mapTag; collectionType = TypeRegistry.GetCollectionType(thatField); break; } switch (annotationType) { case FieldTypes.CollectionElement: case FieldTypes.MapElement: if (!XmlTools.IsAnnotationPresent <SimplNoWrap>(thatField)) { _wrapped = true; } collectionType = TypeRegistry.GetCollectionType(thatField); break; case FieldTypes.CompositeElement: if (XmlTools.IsAnnotationPresent <SimplWrap>(thatField)) { _wrapped = true; } break; } return(result); }
public FieldDescriptor(ClassDescriptor declaringClassDescriptor, FieldInfo field, int annotationType) : base(XmlTools.GetXmlTagName(field), field.Name) { this.declaringClassDescriptor = declaringClassDescriptor; this.field = field; fieldType = field.FieldType.Name; //generics if (field.FieldType.IsGenericParameter || field.FieldType.GetTypeInfo().IsGenericType) { Type realFieldType = field.FieldType; while (realFieldType.IsGenericParameter) { Type[] realFieldTypeConstraints = realFieldType.GetTypeInfo().GetGenericParameterConstraints(); if (realFieldTypeConstraints == null || realFieldTypeConstraints.Length == 0) { realFieldType = typeof(Object); break; } else { realFieldType = realFieldTypeConstraints[0]; } } fieldType = realFieldType.Name; if (realFieldType.GetTypeInfo().IsGenericType)//can also be a generic parameter that extends a generic type { int pos = fieldType.IndexOf('`'); fieldType = fieldType.Substring(0, pos); } } if (XmlTools.IsAnnotationPresent <SimplMapKeyField>(field)) { mapKeyFieldName = XmlTools.GetAnnotation <SimplMapKeyField>(field).FieldName; } DerivePolymorphicDescriptors(field); type = FieldTypes.UnsetType; if (annotationType == FieldTypes.Scalar) { type = DeriveScalarSerialization(field); } else { type = DeriveNestedSerialization(field, annotationType); } String fieldName = field.Name; StringBuilder capFieldName = new StringBuilder(fieldName); //generics Type genericType = field.DeclaringType; isGeneric = genericType.GetTypeInfo().IsGenericType || genericType.IsGenericParameter; }