ビジネスロジックエラー(必ずしも引数エラーなどである必要はありません)に対して私たちがしたいことは、すべての潜在的なタイプのエラーを定義する単一の列挙を持つことです。
/// <summary>
/// This enum is used to identify each business rule uniquely.
/// </summary>
public enum BusinessRuleId {
/// <summary>
/// Indicates that a valid body weight value of a patient is missing for dose calculation.
/// </summary>
[Display(Name = @"DoseCalculation_PatientBodyWeightMissing")]
PatientBodyWeightMissingForDoseCalculation = 1,
/// <summary>
/// Indicates that a valid body height value of a patient is missing for dose calculation.
/// </summary>
[Display(Name = @"DoseCalculation_PatientBodyHeightMissing")]
PatientBodyHeightMissingForDoseCalculation = 2,
// ...
}
[Display(Name = "...")]
属性は、エラーメッセージを翻訳するために使用するリソースファイルでキーを定義します。
また、このファイルは、特定のタイプのエラーがコードで生成されるすべての発生を見つけるための開始点として使用できます。
ビジネスルールのチェックは、違反したビジネスルールのリストを生成する専用のValidatorクラスに委任できます。
次に、カスタム例外タイプを使用して、違反したルールを転送します。
[Serializable]
public class BusinessLogicException : Exception {
/// <summary>
/// The Business Rule that was violated.
/// </summary>
public BusinessRuleId ViolatedBusinessRule { get; set; }
/// <summary>
/// Optional: additional parameters to be used to during generation of the error message.
/// </summary>
public string[] MessageParameters { get; set; }
/// <summary>
/// This exception indicates that a Business Rule has been violated.
/// </summary>
public BusinessLogicException(BusinessRuleId violatedBusinessRule, params string[] messageParameters) {
ViolatedBusinessRule = violatedBusinessRule;
MessageParameters = messageParameters;
}
}
バックエンドサービスコールは、違反したビジネスルールをユーザーが読み取り可能なエラーメッセージに変換する一般的なエラー処理コードにラップされます。
public object TryExecuteServiceAction(Action a) {
try {
return a();
}
catch (BusinessLogicException bex) {
_logger.Error(GenerateErrorMessage(bex));
}
}
public string GenerateErrorMessage(BusinessLogicException bex) {
var translatedError = bex.ViolatedBusinessRule.ToTranslatedString();
if (bex.MessageParameters != null) {
translatedError = string.Format(translatedError, bex.MessageParameters);
}
return translatedError;
}
これToTranslatedString()
は、属性enum
からリソースキーを読み取り[Display]
、ResourceManager
これらのキーを変換するために使用できる拡張メソッドです。各リソースキーの値は、のプレースホルダ含むことができstring.Format
提供一致しますMessageParameters
。resxファイルのエントリの例:
<data name="DoseCalculation_PatientBodyWeightMissing" xml:space="preserve">
<value>The dose can not be calculated because the body weight observation for patient {0} is missing or not up to date.</value>
<comment>{0} ... Patient name</comment>
</data>
使用例:
throw new BusinessLogicException(BusinessRuleId.PatientBodyWeightMissingForDoseCalculation, patient.Name);
このアプローチを使用すると、新しいタイプのエラーごとに新しい例外クラスを導入する必要なく、エラーメッセージの生成をエラーの生成から切り離すことができます。異なるフロントエンドが異なるメッセージを表示する必要がある場合、表示されるメッセージがユーザーの言語やロールなどに依存する必要がある場合に役立ちます。