2024年11月10日 星期日

FHIR SDK(DotNet)- Resource Type - Complex (Patient)

Patient這個Resource是FHIR應用中最常碰到的(另一個是Encounter)。他的結構夠複雜,可以涵蓋許多面向。


如圖中用紅框所示。一個是Choice Type,另一個是BackboneElement。
Choice要注意的是他可能會有不同的資料型態,而且要注意Tag名稱的變化。
BackboneElement他是繼承Element的類別。屬於此資料型態者,就表示會有自己專屬的Element。
而這兩個東西,是跟著所屬的Resource,不可共享。注意,有些地方名稱會一樣,但實際內容是不同的。(有規則就有例外,有部份BackboneElement是參考同一個Resource其他Path下的相同結構的BackboneElement,可參考ImplementationGuide的page)
在程式中這兩個傢伙就得小心處理。

原則上,欄位宣告這些都沒有特別差異。僅需注意紅框是為了Choice Type,而白框是為了BackboneElement。注意參照型態的類別名稱並不會影響JSON內容的判讀。
====Choice Type=====
 

他繼承了ChoiceType,要把自己的element name送給父類別,並且把可選擇的資料型態也定義好即可。(再強調一下,這些內容都是程式產生的)

=====BackboneElement=====

看到這,咦!不就是Complex Type嗎?對呀就是扣除Primity Type+Element那段亂流之外,其實所有結構都是對應到類別呀。為了共用程式碼所以繼承了BackboneElementType<T>,這類別就是繼承了BackboneElement。

所以,全劇終。(但~還是有陷阱)





FHIR SDK(DotNet)- Resource Type - Simple (Basic)

Basic這個Resouce是神奇的存在著。他沒什麼用途,但每次開發系統,一定會先拿他來測試。這裡當然不例外,可惜他真的太單純,無法涵蓋所有面向。

這個Resource沒什麼特殊性,就跟Complex Type一樣,就是有一堆欄位,因繼承DomainResource,所以還會多一些欄位。
所以,程式的部份也沒有什麼特殊性,也就跟ComplexType差不多,只是這邊繼承了ResourceType<T>(上篇已介紹),而不是DomainResource。這是為了拉出實做共同性。這邊的OnPropertyChanged是Resource系列自己的,就不是用DataType那邊的。還有[0..*]是用了List<T>這個資料型態。因為(1) 使用 reflection機制,(2) 要抓JsonArray,幾經實驗,用這個最保險。

這個版本的SDK還沒有把Binding機制做上去,坦白說,還不知道怎麼處理。
另外Reference也沒有把Resource限制進行處理。其實在應用沒有什麼影響。除非是要搞驗證,就需要補上。
=========
透露一下,這裡面的程式碼,都是用另一個專案產生的。這又是另一個技術門檻。















2024年11月9日 星期六

FHIR SDK(DotNet)- FHIR Type Framework - Resource

Resource系列雖然可視為Complex Type,但仍須獨立視之,否則到處都是地雷。在其他的Resource,例如Bundle,其元素entry/resource的資料型態就是Resource。但Resource是抽象型態(Abstract Class),在C#中是不能產生實例。這塊就是得想辦法克服之處。

Resource直接繼承了Base,其所含的元素,乍看之下沒有什麼特殊性。比較麻煩的是meta,他的資料型態是Meta。Meta繼承DataType,所以,他沒有Extension機制。

那Extension機制呢?哈~怎麼可能遺漏呢?原來是放在了DomainResource,而且一次給妳兩個,extension與modifierExtension。(這兩者差異不在本系列範疇)。contained的資料型態是Resource,是他的父類別。這個問題不大,這個類別沒有特別要處理的。


至於其子類別CanonicalResource與在下一個子類別MetadataResource,這兩個定義是介面,表示某些類別需要實做這兩個。例如ActiveDefinition在其結構描述中就有指定要實做MetadataResource。在這兩個介面描述就會說明實做資源相對應條件要求。這塊SDK並沒有實做。


===============

Resource類別的設計與Complex Type類似,只是OnPropertyChange與SetupPropertyValue需要另外處理。(因為Resource直接繼承了base,而這些功能不能寫在Base,因為Datatype那邊有個Element,處理方式略有不同。)


DomainResource更簡單,就是單純的ComplexType。


之前也說過,Resource 是抽象類別,無法直接產生實例。所以,透過可實做類別來實現之。多一個ResourceType類別,硬是把所有Resource都變成Complex Type一樣的操作方式。





2024年11月2日 星期六

FHIR SDK(DotNet)- FHIR Type Framework - BackboneType, BackboneElement

 在Base Type的Element這邊系列中,長了兩個很奇怪的類別BackboneElement繼承了Element,而BackboneType繼承了DataType,兩個類別的欄位內容卻一模一樣。這到底是怎麼一回事呢?

這個設計很明顯就是為了實踐FHIR所強調的20-80理論,但也苦了實做者。
先來看這張圖:

=====BackboneType=====

原來BackboneType其實就是為了幾個Complex Type擁有modifierExtension的機制。有哪幾個呢?依據文件,目前(是的,只能說目前,未來還是有可能增加)Timing、Dosage與ElementDefinition這三個DataType。注意了,我拿Address與Timing來比對。

文件中,兩者都是繼承了Element。所有的Complex Type都是寫繼承Element,沒有DataType。僅能從描述中得知Timing繼承了一個modifierExtension的屬性。這個程式碼單純,就是ComplexType的一種。就不多做解釋了。

=====BackboneElement=====
一定很好奇,除了Base Types的圖中有看到BackboneElement之外,他到底在哪裡呢?原來,他在Resource那邊。找個大家熟悉的Patient Resource吧。

原來他也是一種DataType,但是,他僅是抽象類別,實際的內容還是要看此Elmenet之下的宣告。有感應到了嗎?原則上所有的資料型態都會有extension,但是這類BackboneElement的類別,還會多了modifierExtension。(與BackboneType給的邏輯不太相同)。
BackboneElement的設計架構非常複雜。首先,他會有一個抽象類別,就跟BackboneType一樣,要有modifierExtension屬性。

而分散在Resource裡的BackboneElement,其結構每一個都不一樣。所以,得為每一個不同的BackboneElement設計共用父類別,而這個父類別必須走Reflect架構,這樣子才能夠因應不同的BackboneElement。這個類別的程式非常複雜,也不好解釋。有緣再說了。

來看一下Resource類別是怎麼設計的。仍以Patient Resource為例。
Resource本身當然是繼承了ResourceType系列,這部份後續才會說明。
而Patient Resource裡面的BackboneElement必須帶入類別,這樣子才會知道有哪些欄位屬性,這才方便進行後續處理。

補充說明一下:這個Resource類別的產生,是另一個專案用T4技術自動化產生。這塊技術也是有緣再說明吧。(哈~畢竟一路走來,都是自言自語比較多)