先總結:泛型抽象類/泛型接口就是用抽象類和接口去約束派生類,但是爲了統一實現方法,需要知道派生類的類型,然後傳給基類,通過反射實現封裝。
最近在做醫療設備的對接,就免不了接觸HL7協議,相比於Json格式,它更節省數據長度,更適合與嵌入式系統的消息交互。
首先了解HL7的消息格式主要分爲段和域,多個域組成一個段,多個段組成一個消息。
如下:
MSH|^~\&|LIS|TLA||202201011123||ORU^R01|||||<CR>
PID|||||||||||||||||||||||||||||||||||||||||<CR>
OBR|||||||||||||||||||||||||||||||||||||||||<CR>
域就是|之間的內容,也就是我們的字段,對照協議去解析具體數據,以|分隔。段就是MSH PID OBR,來代表消息頭、患者信息、樣本信息等,以回車符
那麼我們的HL7消息對象的設計就是:
public class ORU_R01{
public MSH MSH{get;set;}
public PID PID{get;set;}
public OBR OBR{get;set;}
}
public class MSH{
public string A{get;set;}
public string B{get;set;}
…… …… ……
}
public class PID{
public string A{get;set;}
public string B{get;set;}
…… …… ……
}
- HL7序列化
要把ORU_R01 轉換成HL7格式的字符串,就必須把MSH PID OBR 轉換成字符串,然後以
public interface IHL7
{
string ToString();
}
這樣就可以在MSH PID OBR 中這樣寫了:
public class MSH:IHL7 {
public string A{get;set;}
public string B{get;set;}
…… …… ……
public string ToString(){
return $"{A}|{B}|{C}|……";
}
}
public class PID{
public string A{get;set;}
public string B{get;set;}
…… …… ……
public string ToString(){
return $"{A}|{B}|{C}|……";
}
}
然後 ORU_R01就可以寫成:
public class ORU_R01:IHL7{
public MSH MSH{get;set;}
public PID PID{get;set;}
public OBR OBR{get;set;}
public string ToString(){
return $"{MSH.ToString()}\r{PID.ToString()}\r{OBR.ToString()}\r…………";
}
}
這樣在HL7序列化時,就不需要知道是ORU_R01還是MSH了,反正IHL7.ToString() 就可以了。
但是情況往往沒這麼簡單,因爲我們的消息會隨着業務的增加而增加,ORU_R01、R02、R03………… 消息段也會不斷的增加,每一個對象都實現一個ToString(),顯然很麻煩,而且一旦有變化,每個類都需要修改,這很不簡單。
這時候我們可以用一個泛型抽象去繼承IHL7接口,並通過反射,統一實現所有的ToString():
public abstract BaseHL7<T>:IHL7 where T:IHL7
{
//爲了往後擴展,使用virtual
protected virtual string ToString(char Separator='|') //默認以|分隔
{
var properties=GetType().GetProperties(BindingFlags.Instance|BindingFlags.Public|BindingFlags.DeclareOnly);//獲取所有的屬性
var datas=properties.Select(t=>{
dynamic itemdata=t.GetValue(this,null);
return itemdata?.Tostring();
});
}
//因爲object 自帶 ToString() 所以不用實現接口的ToString(),不過這裏我們需要調用ToString(char Separator='|'),所以可以有三種寫法,三選一就行,調用IHL7的時候 都會執行。
1.顯示實現IHL7.ToString()
string IHL7.ToString()
{
ToString('|')
}
2.overrid object.ToString()
public overrid ToString()
{
ToString('|')
}
3. new ToString()
public new ToString()
{
ToString('|')
}
}
有了BaseHL7
public class ORU_R01:BaseHL7<ORU_R01>{
public MSH MSH{get;set;}
public PID PID{get;set;}
public OBR OBR{get;set;}
public overried string ToString()
{
return ToString('\r');
}
}
public class MSH:BaseHL7<MSH>{
public string A{get;set;}
public string B{get;set;}
…… …… ……
}
public class PID:BaseHL7<PID>{
public string A{get;set;}
public string B{get;set;}
…… …… ……
}
到此,我們的序列化就完成了。