internal static PropertyMapping Create(PropertyInfo prop, out IEnumerable<Type> referredTypes) { if (prop == null) throw Error.ArgumentNull("prop"); var foundTypes = new List<Type>(); PropertyMapping result = new PropertyMapping(); #if (PORTABLE45 || NETCOREAPP1_1) var elementAttr = prop.GetCustomAttribute<FhirElementAttribute>(); #else var elementAttr = (FhirElementAttribute)Attribute.GetCustomAttribute(prop, typeof(FhirElementAttribute)); #endif result.Name = determinePropertyName(prop); result.ReturnType = prop.PropertyType; result.ElementType = result.ReturnType; result.InSummary = elementAttr != null ? elementAttr.InSummary : 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; }
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); }
//private static void checkMutualExclusiveAttributes(Type type) //{ // if (ClassMapping.IsFhirResource(type) && ClassMapping.IsFhirComplexType(type)) // throw Error.Argument("type", "Type {0} cannot be both a Resource and a Complex datatype", type); // if (ClassMapping.IsFhirResource(type) && ClassMapping.IsFhirPrimitive(type)) // throw Error.Argument("type", "Type {0} cannot be both a Resource and a Primitive datatype", type); // if (ClassMapping.IsFhirComplexType(type) && ClassMapping.IsFhirPrimitive(type)) // throw Error.Argument("type", "Type {0} cannot be both a Complex and a Primitive datatype", type); //} //private static object invokeEnumParser(string input, Type enumType) //{ // object result = null; // bool success = EnumHelper.TryParseEnum(input, enumType, out result); // if (!success) // throw Error.InvalidOperation("Parsing of enum failed"); // return result; //} private static string getProfile(Type type) { var attr = ReflectionHelper.GetAttribute <FhirTypeAttribute>(type); return(attr != null ? attr.Profile : null); }