internal static PropertyMapping Create(PropertyInfo prop, out IEnumerable <Type> referredTypes) { if (prop == null) { throw Error.ArgumentNull(nameof(prop)); } var foundTypes = new List <Type>(); PropertyMapping result = new PropertyMapping(); var elementAttr = prop.GetCustomAttribute <FhirElementAttribute>(); var cardinalityAttr = prop.GetCustomAttribute <Validation.CardinalityAttribute>(); result.Name = determinePropertyName(prop); result.ReturnType = prop.PropertyType; result.ElementType = result.ReturnType; result.InSummary = elementAttr != null ? elementAttr.InSummary : false; result.IsMandatoryElement = cardinalityAttr != null ? cardinalityAttr.Min > 0 : false; result.Choice = elementAttr != null ? elementAttr.Choice : ChoiceType.None; if (elementAttr != null) { result.SerializationHint = elementAttr.XmlSerialization; result.Order = elementAttr.Order; } foundTypes.Add(result.ElementType); result.IsCollection = ReflectionHelper.IsTypedCollection(prop.PropertyType) && !prop.PropertyType.IsArray; // Get to the actual (native) type representing this element if (result.IsCollection) { result.ElementType = ReflectionHelper.GetCollectionItemType(prop.PropertyType); } if (ReflectionHelper.IsNullableType(result.ElementType)) { result.ElementType = ReflectionHelper.GetNullableArgument(result.ElementType); } result.IsPrimitive = isAllowedNativeTypeForDataTypeValue(result.ElementType); // Check wether this property represents a native .NET type // marked to receive the class' primitive value in the fhir serialization // (e.g. the value from the Xml 'value' attribute or the Json primitive member value) if (result.IsPrimitive) { result.RepresentsValueElement = isPrimitiveValueElement(prop); } referredTypes = foundTypes; // May need to generate getters/setters using pre-compiled expression trees for performance. // See http://weblogs.asp.net/marianor/archive/2009/04/10/using-expression-trees-to-get-property-getter-and-setters.aspx result._getter = instance => prop.GetValue(instance, null); result._setter = (instance, value) => prop.SetValue(instance, value, null); return(result); }
//public Type GetChoiceType(string choiceSuffix) //{ // string suffix = choiceSuffix.ToUpperInvariant(); // if(!HasChoices) return null; // return _choices // .Where(cattr => cattr.TypeName.ToUpperInvariant() == suffix) // .Select(cattr => cattr.Type) // .FirstOrDefault(); //} private static bool isAllowedNativeTypeForDataTypeValue(Type type) { // Special case, allow Nullable<enum> if (ReflectionHelper.IsNullableType(type)) type = ReflectionHelper.GetNullableArgument(type); return type.IsEnum() || PrimitiveTypeConverter.CanConvert(type); }
internal static PropertyMapping Create(PropertyInfo prop, out IEnumerable <Type> referredTypes) { if (prop == null) { throw Error.ArgumentNull(nameof(prop)); } var foundTypes = new List <Type>(); PropertyMapping result = new PropertyMapping(); var elementAttr = prop.GetCustomAttribute <FhirElementAttribute>(); var cardinalityAttr = prop.GetCustomAttribute <Validation.CardinalityAttribute>(); var allowedTypes = prop.GetCustomAttribute <Validation.AllowedTypesAttribute>(); result.Name = determinePropertyName(prop); result.ImplementingType = prop.PropertyType; result.InSummary = elementAttr?.InSummary ?? false; result.IsMandatoryElement = cardinalityAttr != null ? cardinalityAttr.Min > 0 : false; result.Choice = elementAttr?.Choice ?? ChoiceType.None; if (elementAttr != null) { result.SerializationHint = elementAttr.XmlSerialization; result.Order = elementAttr.Order; } result.IsCollection = ReflectionHelper.IsTypedCollection(prop.PropertyType) && !prop.PropertyType.IsArray; // Get to the actual (native) type representing this element if (result.IsCollection) { result.ImplementingType = ReflectionHelper.GetCollectionItemType(prop.PropertyType); } if (ReflectionHelper.IsNullableType(result.ImplementingType)) { result.ImplementingType = ReflectionHelper.GetNullableArgument(result.ImplementingType); } result.IsPrimitive = isAllowedNativeTypeForDataTypeValue(result.ImplementingType); result.IsBackboneElement = result.ImplementingType.CanBeTreatedAsType(typeof(IBackboneElement)); foundTypes.Add(result.ImplementingType); // Derive the C# type that represents which types are allowed for this element. // This may differ from the ImplementingType in several ways: // * for a choice, ImplementingType = Any, but FhirType[] contains the possible choices // * some elements (e.g. Extension.url) have ImplementingType = string, but FhirType = FhirUri, etc. if (allowedTypes != null) { result.FhirType = allowedTypes.Types; } else if (elementAttr?.TypeRedirect != null) { result.FhirType = new[] { elementAttr.TypeRedirect } } ; else { result.FhirType = new[] { result.ImplementingType } }; // Check wether this property represents a native .NET type // marked to receive the class' primitive value in the fhir serialization // (e.g. the value from the Xml 'value' attribute or the Json primitive member value) if (result.IsPrimitive) { result.RepresentsValueElement = isPrimitiveValueElement(prop); } referredTypes = foundTypes; #if USE_CODE_GEN result._getter = prop.GetValueGetter(); result._setter = prop.GetValueSetter(); #else result._getter = instance => prop.GetValue(instance, null); result._setter = (instance, value) => prop.SetValue(instance, value, null); #endif return(result); }