diff --git a/Excely.UnitTests/ClassListTableConverterTests.cs b/Excely.UnitTests/ClassListTableConverterTests.cs index c81c47f..e4f693f 100644 --- a/Excely.UnitTests/ClassListTableConverterTests.cs +++ b/Excely.UnitTests/ClassListTableConverterTests.cs @@ -299,7 +299,7 @@ public void ConvertFromErrorData_ShouldThrowExceptions() }); var options = new ClassListTableConverterOptions { - StopWhenError = false, + ThrowWhenError = false, }; var converter = new ClassListTableConverter(); @@ -323,7 +323,7 @@ public void ConvertFromErrorData_ShouldRecordErrorAndReturnListWithoutErrorRecor var errors = new Dictionary(); var options = new ClassListTableConverterOptions { - StopWhenError = false, + ThrowWhenError = false, ErrorHandlingPolicy = (location, obj, p, value, err) => { errors.Add(location, err); @@ -363,7 +363,7 @@ public void ConvertFromErrorData_ShouldReturnCorrectListWithoutErrorRecords() }); var options = new ClassListTableConverterOptions { - StopWhenError = false, + ThrowWhenError = false, }; var converter = new ClassListTableConverter(options); @@ -397,7 +397,7 @@ public void ConvertFromErrorData_ShouldReturnListWithFixedData() var errors = new Dictionary(); var options = new ClassListTableConverterOptions { - StopWhenError = false, + ThrowWhenError = false, ErrorHandlingPolicy = (location, obj, p, value, err) => { p.SetValue(obj, null); diff --git a/Excely/TableConverters/ClassListTableConverter.cs b/Excely/TableConverters/ClassListTableConverter.cs index fdf46e0..958967c 100644 --- a/Excely/TableConverters/ClassListTableConverter.cs +++ b/Excely/TableConverters/ClassListTableConverter.cs @@ -135,7 +135,7 @@ private IEnumerable ImportInternal(ExcelyTable table, Func /// 當轉換發生錯誤時是否立刻停止。 /// 若此欄為 false,則發生錯誤時會跳過該 Row,繼續執行匯入。 /// - public bool StopWhenError { get; set; } = true; + public bool ThrowWhenError { get; set; } = true; + + /// + /// 當寫入的值與目標型別不同時,是否自動嘗試轉換。 + /// + public bool EnableAutoTypeConversion { get; set; } = true; /// /// 決定 Property 作為欄位時的名稱。 - /// 輸入參數為 PropertyInfo,輸出結果為「欄位名稱」, - /// 預設為 Property.Name。 + /// 預設為 PropertyInfo.Name /// - public Func PropertyNamePolicy { get; set; } = prop => prop.Name; + public PropertyNamePolicyDelegate PropertyNamePolicy { get; set; } = property => property.Name; /// - /// 決定 Property 出現在表頭時的位置。 - /// 輸入參數為 (所有Properties, PropertyInfo),輸出結果為「欄位索引」, - /// 若該 Property 沒有出現在表頭中,請回傳 null。 - /// 預設為依照 property 預設順序排序。 + /// 取得 Property 出現在表頭時的位置。 + /// 預設為依類別內預設排序。 /// - public Func PropertyIndexPolicy { get; set; } = (props, prop) => Array.IndexOf(props, prop); + public PropertyIndexPolicyDelegate PropertyIndexPolicy { get; set; } = (propertys, property) => Array.IndexOf(propertys, property); /// /// 決定將值寫入至 Property 時應寫入的值。 - /// 輸入參數為 (PropertyInfo, 原始值),輸出結果為「應寫入的值」。 /// 預設為原值。 /// - public Func PropertyValueSettingPolicy { get; set; } = (prop, obj) => obj; + public PropertyValueSettingPolicyDelegate PropertyValueSettingPolicy { get; set; } = (prop, obj) => obj; /// /// 將值輸入進物件發生錯誤時,決定錯誤處理方式。 - /// 輸入參數為 (儲存格座標, 目標物件, PropertyInfo, 嘗試輸入的值, 發生的錯誤),輸出結果為「錯誤是否得到修正」。 /// 預設為不處理錯誤。 /// - public Func ErrorHandlingPolicy { get; set; } = (_, _, _, _, _) => false; + public ErrorHandlingPolicyDelegate ErrorHandlingPolicy { get; set; } = (_, _, _, _, _) => false; + + #region ===== Policy delegates ===== /// - /// 當寫入的值與目標型別不同時,是否自動嘗試轉換。 + /// 取得 Property 作為欄位時的名稱。 /// - public bool EnableAutoTypeConversion { get; set; } = true; + /// 當前決定的 Property + /// 欄位名稱 + public delegate string? PropertyNamePolicyDelegate(PropertyInfo property); + + /// + /// 取得 Property 作為欄位時的位置。 + /// + /// 目標類別的所有 Property + /// 當前決定的 Property + /// 欄位權重(越小越靠前),若回傳 null,代表此 Property 沒有對應的欄位 + public delegate int? PropertyIndexPolicyDelegate(PropertyInfo[] allProperties, PropertyInfo property); + + /// + /// 決定將值寫入至 Property 時應寫入的值。 + /// + /// 當前寫入欄位 + /// 原始讀取到的值 + /// 欲寫入的值 + public delegate object? PropertyValueSettingPolicyDelegate(PropertyInfo property, object? originalValue); + + /// + /// 將值輸入進物件發生錯誤時,決定錯誤處理方式。 + /// + /// 發生錯誤的座標 + /// 正在寫入的目標物件 + /// 正在寫入的目標 Property + /// 嘗試寫入的值 + /// 發生的錯誤 + /// 錯誤是否得到修正 + public delegate bool ErrorHandlingPolicyDelegate( + CellLocation cellLocation, + TClass writtingObject, + PropertyInfo writtingProperty, + object? writtingValue, + Exception exception); + + #endregion ===== Policy delegates ===== } } diff --git a/Excely/TableConverters/DictionaryListTableConverter.cs b/Excely/TableConverters/DictionaryListTableConverter.cs index f32df47..6d726ab 100644 --- a/Excely/TableConverters/DictionaryListTableConverter.cs +++ b/Excely/TableConverters/DictionaryListTableConverter.cs @@ -1,4 +1,7 @@ -namespace Excely.TableConverters +using System.Formats.Asn1; +using System.Reflection; + +namespace Excely.TableConverters { /// /// 將 Table 轉換為字典列表。 @@ -84,18 +87,35 @@ public class DictionaryListTableConverterOptions /// /// 決定欄位作為 Key 時的名稱。 - /// 輸入參數為 (欄位index, 欄位名稱),輸出結果為 Key, /// 若 HasSchema 為 false 時,欄位名稱將是 null。 /// 預設為 (欄位名稱 ?? 欄位index)。 - /// 若 return null,代表此欄位不匯入。 /// - public Func CustomKeyNamePolicy { get; set; } = (index, fieldName) => fieldName ?? index.ToString(); + public CustomKeyNamePolicyDelegate CustomKeyNamePolicy { get; set; } = (index, fieldName) => fieldName ?? index.ToString(); /// /// 決定將值寫入至 Vale 時應寫入的值。 - /// 輸入參數為 (Key, 原始值),輸出結果為「應寫入的值」。 /// 預設為原值。 /// - public Func CustomValuePolicy { get; set; } = (key, value) => value; + public CustomValuePolicyDelegate CustomValuePolicy { get; set; } = (key, value) => value; + + #region ===== Policy delegates ===== + + /// + /// 決定欄位作為 Key 時的名稱。 + /// + /// 欄位index + /// 欄位名稱 + /// 用作 key 的字串,若回傳 null,代表此欄位不匯入 + public delegate string? CustomKeyNamePolicyDelegate(int fieldIndex, string? fieldName); + + /// + /// 決定將值寫入至 Vale 時應寫入的值。 + /// + /// 代表此欄的 key 值 + /// 原始讀取到的值 + /// 應寫入的值 + public delegate object? CustomValuePolicyDelegate(string key, object? originalValue); + + #endregion ===== Policy delegates ===== } } diff --git a/Excely/TableFactories/ClassListTableFactory.cs b/Excely/TableFactories/ClassListTableFactory.cs index 87960e9..d343210 100644 --- a/Excely/TableFactories/ClassListTableFactory.cs +++ b/Excely/TableFactories/ClassListTableFactory.cs @@ -85,31 +85,61 @@ public class ClassListTableFactoryOptions public bool WithSchema { get; set; } = true; /// - /// 決定 Property 是否應作為欄位匯出的執行邏輯。 - /// 輸入參數為 PropertyInfo,輸出結果為「是否應作為欄位匯出」, + /// 決定 Property 是否應作為欄位匯出。 /// 預設為全部欄位都匯出。 /// - public Func PropertyShowPolicy { get; set; } = _ => true; + public PropertyShowPolicyDelegate PropertyShowPolicy { get; set; } = _ => true; /// /// 決定 Property 作為欄位時的名稱。 - /// 輸入參數為 PropertyInfo,輸出結果為「欄位名稱」, /// 預設為 PropertyInfo.Name。 /// - public Func PropertyNamePolicy { get; set; } = p => p.Name; + public PropertyNamePolicyDelegate PropertyNamePolicy { get; set; } = property => property.Name; /// /// 決定 Property 作為欄位時的順序。 - /// 輸入參數為 (所有Properties, 當前PropertyInfo),輸出結果為「排序(由小到大)」, /// 預設為依類別內預設排序。 /// - public Func PropertyOrderPolicy { get; set; } = (properties, p) => Array.IndexOf(properties, p); + public PropertyOrderPolicyDelegate PropertyOrderPolicy { get; set; } = (properties, property) => Array.IndexOf(properties, property); /// /// 決定資料寫入欄位時的值。 - /// 輸入參數為 (PropertyInfo, 當前匯出物件),輸出結果為「欲寫入欄位的值」, /// 預設為該 Property 之 Value。 /// - public Func CustomValuePolicy { get; set; } = (p, obj) => p.GetValue(obj); + public CustomValuePolicyDelegate CustomValuePolicy { get; set; } = (property, obj) => property.GetValue(obj); + + #region ===== Policy delegates ===== + + /// + /// 決定 Property 是否應作為欄位匯出。 + /// + /// 當前決定的 Property + /// 是否應匯出 + public delegate bool PropertyShowPolicyDelegate(PropertyInfo property); + + /// + /// 決定 Property 作為欄位時的名稱。 + /// + /// 當前決定的 Property + /// 欄位名稱 + public delegate string? PropertyNamePolicyDelegate(PropertyInfo property); + + /// + /// 決定 Property 作為欄位時的順序。 + /// + /// 目標類別的所有 Property + /// 當前決定的 Property + /// 欄位權重(越小越靠前) + public delegate int? PropertyOrderPolicyDelegate(PropertyInfo[] allProperties, PropertyInfo property); + + /// + /// 決定資料寫入欄位時的值。 + /// + /// 當前決定的 Property + /// 當前寫入的目標物件 + /// 應寫入的值 + public delegate object? CustomValuePolicyDelegate(PropertyInfo property, TClass obj); + + #endregion ===== Policy delegates ===== } } diff --git a/Excely/TableFactories/DictionaryListTableFactory.cs b/Excely/TableFactories/DictionaryListTableFactory.cs index e547c56..0216dfb 100644 --- a/Excely/TableFactories/DictionaryListTableFactory.cs +++ b/Excely/TableFactories/DictionaryListTableFactory.cs @@ -1,4 +1,7 @@ -namespace Excely.TableFactories +using System.Formats.Asn1; +using System.Reflection; + +namespace Excely.TableFactories { /// /// 提供以字典 Key 為欄位,將字典集合傾印至表格的功能。 @@ -74,31 +77,61 @@ public class DictionaryListTableFactoryOptions public bool WithSchema { get; set; } = true; /// - /// 決定 key 是否應作為欄位匯出的執行邏輯。 - /// 輸入參數為 key,輸出結果為「是否應作為欄位匯出」, + /// 決定 key 是否應作為欄位匯出。 /// 預設為全部欄位都匯出。 /// - public Func KeyShowPolicy { get; set; } = _ => true; + public KeyShowPolicyDelegate KeyShowPolicy { get; set; } = _ => true; /// /// 決定 key 作為欄位時的名稱。 - /// 輸入參數為 key,輸出結果為「欄位名稱」, /// 預設為 key。 /// - public Func KeyNamePolicy { get; set; } = k => k; + public KeyNamePolicyDelegate KeyNamePolicy { get; set; } = key => key; /// - /// 決定 key 作為欄位時的順序。 - /// 輸入參數為 (所有key(預設排序), key),輸出結果為「排序(由小到大)」, - /// 預設為依 key 出現順序排序。 + /// 決定 key 作為欄位時的權重(越小越靠前)。 + /// 預設為 key 的預設順序。 /// - public Func KeyOrderPolicy { get; set; } = (keys, k) => Array.IndexOf(keys, k); + public KeyOrderPolicyDelegate KeyOrderPolicy { get; set; } = (allKeys, key) => Array.IndexOf(allKeys, key); /// /// 決定資料寫入欄位時的值。 - /// 輸入參數為 (key, 當前匯出物件),輸出結果為「欲寫入欄位的值」, /// 預設為 Value。 /// - public Func, object?> CustomValuePolicy { get; set; } = (k, dict) => dict.GetValueOrDefault(k, null); + public CustomValuePolicyDelegate CustomValuePolicy { get; set; } = (key, dict) => dict.GetValueOrDefault(key, null); + + #region ===== Policy delegates ===== + + /// + /// 決定 key 是否應作為欄位匯出。 + /// + /// 當前決定的 key + /// 是否應匯出 + public delegate bool KeyShowPolicyDelegate(string key); + + /// + /// 決定 key 作為欄位時的名稱。 + /// + /// 當前決定的 key + /// 欄位名稱 + public delegate string? KeyNamePolicyDelegate(string key); + + /// + /// 決定 key 作為欄位時的權重(越小越靠前)。 + /// + /// 所有 key + /// 當前決定的 key + /// 欄位權重 + public delegate int KeyOrderPolicyDelegate(string[] allKeys, string key); + + /// + /// 決定資料寫入欄位時的值。 + /// + /// 當前決定的 key + /// 當前正在寫入的 Dictionary + /// 應寫入的值 + public delegate object? CustomValuePolicyDelegate(string key, Dictionary writtingDict); + + #endregion ===== Policy delegates ===== } }