如何基于FHIR自定义Profile生成可序列化的C#类?
Great question—generating C# classes from custom FHIR Profiles that support serialization/deserialization and enforce Profile constraints is a common challenge when working with FHIR base resources. Here are several practical, proven methods to pull this off:
1. Use the Firely .NET SDK's Built-in Code Generator
The Firely .NET SDK (the de facto standard for FHIR development in C#) includes a dedicated code generation tool that parses your custom Profile's StructureDefinition (JSON/XML) and emits fully compliant C# classes. These classes inherit directly from the base FHIR resource classes (like Patient, Observation) and come with out-of-the-box serialization/deserialization support.
How to implement this:
- Install the
Firely.Fhir.CodeGeneration.CSharpNuGet package. - Use the
CSharpGeneratorclass in your code (or the command-line utility) to feed it your Profile's StructureDefinition. - The generated classes will automatically include properties for your Profile's extensions, slicing rules, and custom elements. They work seamlessly with the SDK's
FhirSerializer(for JSON/XML serialization) andFhirValidator(to enforce Profile constraints).
This is the fastest, most low-effort approach since it leverages maintained, FHIR-compliant tooling.
2. Manual Class Creation with FHIR Annotations
If you only have a few custom Profiles, you can build classes manually by extending the base FHIR resource classes and using FHIR-specific attributes to align with your Profile's rules.
Example for a custom Patient Profile:
using Hl7.Fhir.Model; using Hl7.Fhir.Serialization; using System; [FhirType("Patient")] public class CustomPatientProfile : Patient { // Map a custom extension defined in your Profile [FhirElement("hospitalPatientIdentifier", IsExtension = true)] public StringType HospitalPatientId { get; set; } // Enforce a mandatory constraint from your Profile public override DateType BirthDate { get => base.BirthDate; set => base.BirthDate = value ?? throw new InvalidOperationException("BirthDate is required per CustomPatientProfile"); } }
- Use
FhirSerializer.SerializeToJson()/FhirSerializer.DeserializeFromJson()to handle serialization. - Validate instances against your Profile using
FhirValidator.Validate()with your Profile's StructureDefinition.
3. T4 Text Templates for Full Customization
If you need complete control over the generated code structure (e.g., adding custom business logic, specific serialization attributes), T4 text templates are a powerful option.
Steps to use T4 templates:
- Load your Profile's StructureDefinition into a
StructureDefinitionobject using the FHIR SDK. - Traverse the definition to extract elements, extensions, constraints, and slicing rules.
- Write a T4 template that generates C# code based on this data—you can define property types, add validation logic, and include serialization attributes (like
JsonPropertyfor Newtonsoft.Json) exactly how you need them.
This approach is ideal if you need to tailor the generated classes to fit into an existing codebase or add non-standard functionality.
Ensuring Profile Compliance
No matter which method you choose, you'll want to pair your classes with validation to enforce your Profile's rules:
- Use the FHIR SDK's
FhirValidatorwith your custom Profile's StructureDefinition to validate instances at runtime. - For compile-time checks, leverage nullable reference types and custom property setters (as shown in the manual example) to catch mandatory field violations early.
All these methods work with FHIR base resources, so you won't have to rebuild core resource properties from scratch. The Firely SDK approach is best for most use cases, while T4 templates give you maximum flexibility for edge cases.
内容的提问来源于stack exchange,提问作者Harsh Agarwal

