需為 int、long、double 等數值型別撰寫相同語意的擴展方法(如 MustBetween、MustGreaterThan)。這些型別無共同繼承體系,初期只能逐型別複製貼上,極不優雅。
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
using System;
namespace Happy.Infrastructure.ExtentionMethods {
public static partial class Check {
<# foreach(var type in new string[]{ "double", "int" }) { #>
/// <summary> 值必須在 [start, end] 範圍內 </summary>
public static void MustBetween(this <#= type #> value, string variableName, <#= type #> start, <#= type #> end) {
Require(value >= start && value <= end, String.Format(Messages.Error_MustBetween, variableName, start, end));
}
/// <summary> 值必須大於 target </summary>
public static void MustGreaterThan(this <#= type #> value, string variableName, <#= type #> target) {
Require(value > target, String.Format(Messages.Error_MustGreaterThan, variableName, target));
}
/// <summary> 值必須大於等於 target </summary>
public static void MustGreaterThanEqual(this <#= type #> value, string variableName, <#= type #> target) {
Require(value >= target, String.Format(Messages.Error_MustGreaterThanEqual, variableName, target));
}
<# } #>
}
}

配合 partial class,T4 產生的部分類別與手寫部分無縫合併,解決重複問題。

所有數值型別都實作IComparable<T>,直接寫泛型擴展方法並約束where T : IComparable<T>即可,無需 T4 產生重複代碼。
public static void MustBetween<T>(this T value, string variableName, T start, T end)
where T : IComparable<T> {
Require(value.CompareTo(start) >= 0 && value.CompareTo(end) <= 0,
String.Format(Messages.Error_MustBetween, variableName, start, end));
}
public static void MustGreaterThan<T>(this T value, string variableName, T target)
where T : IComparable<T> {
Require(value.CompareTo(target) > 0,
String.Format(Messages.Error_MustGreaterThan, variableName, target));
}
public static void MustGreaterThanEqual<T>(this T value, string variableName, T target)
where T : IComparable<T> {
Require(value.CompareTo(target) >= 0,
String.Format(Messages.Error_MustGreaterThanEqual, variableName, target));
}