工作上遇到的問題 , 假設有一堆 Station
的資料表 , 他們都繼承自 IBaseStation
他們有共通基底的屬性 , 但是每個紀錄的參數不同
1 2 3 4 5 6 7 8 9
| public abstract class IBaseStation{ public int Id {get;set;} public string Name {get;set;} }
public class class OOXXStation : IBaseStation{ public double Temp {get;set;} public double Current {get;set;} }
|
這時候有個 Output<T>
泛型方法會去呼叫 , 但是如果用 Output 在 ef core 就會噴 error
如果直接呼叫 Output
則會沒辦法轉成正常型別噴 RuntimeBinderException
1 2 3 4 5 6 7
| public bool Output<T>( StationDto station, int mode, IBaseStation stationTable, out string errorMessage) where T : class{ //logic }
|
一開始想了個笨方法大概這樣 , 有大概數十個站別所以很蠢
1 2 3 4 5 6 7 8 9
| bool isOk = false; Type t = ((object)stationTable).GetType(); if(t == typeof(OOXXStation)){ isOk = ((StationService)_stationService) .Output<OOXXStation>(stationDto, 2, stationTable, out string errorMessage); return isOk; }
|
後來想到應該可以用反射來呼叫 , 大概三個步驟搞定
- 首先先取得 table 的型別
- 接著呼叫泛型方法把型別塞進去
- 丟入參數
比較特別的是原本 function errorMessage
是用 out
去丟出來的
所以給參數的時候要放 null
去接就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Type t = ((object)stationTable).GetType();
MethodInfo outputMethod = typeof(StationService) .GetMethod("Output") .MakeGenericMethod(t);
object[] parameters = new object[] { stationDto, 2, stationTable, null };
string errorMessage = ""; var isOk = outputMethod.Invoke((StationService)_stationService, parameters); if (isOk != null) { if(parameters[3] != null) errorMessage = (string)parameters[3]; }
|