Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Hl7.Fhir.Base/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,13 @@
<Right>lib/net8.0/Hl7.Fhir.Base.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Hl7.Fhir.Utility.ReflectionHelper.FindPublicProperties(System.Type)</Target>
<Left>lib/net8.0/Hl7.Fhir.Base.dll</Left>
<Right>lib/net8.0/Hl7.Fhir.Base.dll</Right>
<IsBaselineSuppression>true</IsBaselineSuppression>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Hl7.Fhir.Utility.ReflectionHelper.IsTypedCollection(System.Type)</Target>
Expand Down
26 changes: 24 additions & 2 deletions src/Hl7.Fhir.Base/Introspection/ClassMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,14 +324,36 @@ private PropertyMappingCollection inspectProperties()

IEnumerable<PropertyMapping> map()
{
foreach (var property in ReflectionHelper.FindPublicProperties(NativeType))
var properties = selectNearestProperties(ReflectionHelper.FindPublicProperties(NativeType));

foreach (var property in properties)
{
if (!PropertyMapping.TryCreate(property, out var propMapping, this, Release)) continue;
yield return propMapping!;
yield return propMapping;
}
}
}

/// <summary>
/// When redefining a property using `new` in a subclass, the property will be present multiple times in the
/// list of properties. This method will select the property from the "closest" declaring type in the
/// inheritance hierarchy to the type of the class mapping.
/// </summary>
private static IEnumerable<PropertyInfo> selectNearestProperties(IReadOnlyCollection<PropertyInfo> properties)
{
var hierarchyComparer = Comparer<PropertyInfo>.Create(compareInheritance);
var ordered = properties.OrderBy(p => p, hierarchyComparer);
return ordered.GroupBy(p => p.Name).Select(g => g.First()).ToList();
}

private static int compareInheritance(PropertyInfo x, PropertyInfo y)
{
if (x.DeclaringType == y.DeclaringType) return 0;
if (x.DeclaringType!.IsAssignableFrom(y.DeclaringType)) return 1;
if (y.DeclaringType!.IsAssignableFrom(x.DeclaringType)) return -1;
return 0;
}

private static string collectTypeName(FhirTypeAttribute attr, Type type)
{
var name = attr.Name;
Expand Down
9 changes: 5 additions & 4 deletions src/Hl7.Fhir.Base/Introspection/PropertyMappingCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ public PropertyMappingCollection(IEnumerable<PropertyMapping> mappings)
foreach (var mapping in mappings)
{
var propKey = mapping.Name;
if (byName.ContainsKey(propKey))
throw Error.InvalidOperation($"Class has multiple properties that are named '{propKey}'. The property name must be unique.");

byName[propKey] = mapping;
if (!byName.TryAdd(propKey, mapping))
{
throw Error.InvalidOperation(
$"Class has multiple properties that are named '{propKey}'. The property name must be unique.");
}
}

ByName = byName;
Expand Down
2 changes: 1 addition & 1 deletion src/Hl7.Fhir.Base/Model/Code.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public partial class Code
/// <summary>
/// Creates a <see cref="ElementModel.Types.Code"/> from an instance of a <see cref="Code"/>.
/// </summary>
public ElementModel.Types.Code ToSystemCode() => new(system: null, code: Value, display: null, version: null);
public virtual ElementModel.Types.Code ToSystemCode() => new(system: null, code: Value, display: null, version: null);

/// <summary>
/// Checks whether the given literal is correctly formatted.
Expand Down
14 changes: 11 additions & 3 deletions src/Hl7.Fhir.Base/Model/CodeOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,15 @@ POSSIBILITY OF SUCH DAMAGE.

namespace Hl7.Fhir.Model
{
/// <summary>
/// A <see cref="Code"/> that has a limited set of values and which <see cref="Code.Value"/> can therefore
/// be represented as an enumerated type.
/// </summary>
[Serializable]
[FhirType("codeOfT")]
[DataContract]
[System.Diagnostics.DebuggerDisplay(@"\{Value={Value}}")]
public class Code<T> : PrimitiveType, INullableValue<T>, ISystemAndCode where T : struct, Enum
public class Code<T> : Code, INullableValue<T>, ISystemAndCode where T : struct, Enum
{
static Code()
{
Expand All @@ -66,7 +70,7 @@ public Code(T? value)
// Primitive value of element
[FhirElement("value", IsPrimitiveValue = true, XmlSerialization = XmlRepresentation.XmlAttr, InSummary = true, Order = 30)]
[DataMember]
public T? Value
new public T? Value
{
get => TryParseObjectValue(out var value)
? value
Expand Down Expand Up @@ -94,7 +98,11 @@ internal bool TryParseObjectValue(out T? value)

string ISystemAndCode.Code => Value?.GetLiteral();

public S.Code ToSystemCode() => new(Value?.GetSystem(), Value?.GetLiteral(), display: null, version: null);
public override S.Code ToSystemCode() =>
new(Value?.GetSystem(),
Value?.GetLiteral() ?? throw new InvalidOperationException("Code must have a value in order to be useable to construct a System.Code."),
display: null,
version: null);

public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Hl7.Fhir.Base/Model/ICoded.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public static class CodedExtensions
public static IEnumerable<Coding> ToCodings(this DataType? dt) => dt switch
{
null => Enumerable.Empty<Coding>(),
Code co => new[] { new Coding(null, co.Value) },
ISystemAndCode sac => new[] { new Coding(sac.System, sac.Code) },
Code co => new[] { new Coding(null, co.Value) },
Coding cd => new[] { cd },
CodeableConcept cc => cc.Coding ?? Enumerable.Empty<Coding>(),
Quantity q => new[] { new Coding(q.System, q.Code) },
Expand Down
2 changes: 1 addition & 1 deletion src/Hl7.Fhir.Base/Utility/ReflectionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static PropertyInfo FindProperty(Type t, string name) =>
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static IEnumerable<PropertyInfo> FindPublicProperties(Type t)
public static PropertyInfo[] FindPublicProperties(Type t)
{
if (t == null) throw Error.ArgumentNull("t");

Expand Down
Loading