IDeliveryObject
を検証するいくつかのバリデーターがありますが、これは概念的には複数の行を持つファイルとして記述できます。その部分は正常に動作しています。LINQの条件付きテイク
IEnumerable<IDeliveryValidator> _validators; // Populated in ctor. Usually around 20 different validators.
private IEnumerable<IValidationResult> Validate(IDeliveryObject deliveryObject)
{
var validationErrors = new List<IValidationResult>();
int maxNumberOfErrors = 10;
foreach (IDeliveryValidator deliveryValidator in _validators)
{
IEnumerable<IValidationResult> results = deliveryValidator.Validate(deliveryObject).Take(maxNumberOfErrors);
validationErrors.AddRange(results);
if (validationErrors.Count >= maxNumberOfErrors)
{
return validationErrors.Take(maxNumberOfErrors).ToList();
}
}
return validationErrors;
}
ロジックは、いくつかのバリデーターを通して繰り返します。バリデーターは、ファイルごとに異なるものを検証します。
そしてバリデータはこのような何か見ることができます:
public IEnumerable<IValidationResult> Validate(IDeliveryObject deliveryObject)
{
using (var reader = File.OpenText(deliveryObject.FilePath))
{
int expectedLength = 10; // Or some other value.
string line;
while ((line = reader.ReadLine()) != null)
{
var lineLength = line.Length;
if (lineLength != expectedLength)
{
// yield an error for each incorrect row.
yield return new DeliveryValidationResult("Wrong length...");
}
}
}
}
ValidationResult
は次のようになります。
public class DeliveryValidationResult : ValidationResult, IValidationResult
{
public DeliveryValidationResult(bool isSoftError, string errorMessage) : base(errorMessage)
{
IsSoftError = isSoftError;
}
public DeliveryValidationResult(string errorMessage) : base(errorMessage)
{
}
public DeliveryValidationResult(string errorMessage, IEnumerable<string> memberNames) : base(errorMessage, memberNames)
{
}
public DeliveryValidationResult(ValidationResult validationResult) : base(validationResult)
{
}
public bool IsSoftError { get; set; }
}
public interface IValidationResult
{
string ErrorMessage { get; set; }
bool IsSoftError { get; set; }
}
おかげTake(maxNumberOfErrors)
とyield
に各バリデータはわずか10 validationresultsを返すでしょう、にするために使用良い。しかし、今では、同じ種類の検証結果である「ソフト検証結果」を処理する必要がありますが、結果の数には含めるべきではありません。これは警告の一種で、IsSoftError
をIValidationResult
に設定することで定義されます。バリデーターは、「ソフト検証結果」と「正規検証結果」の両方を得ることができます。
x検証結果と無制限のソフト検証結果を取得して、IsSoftError == true
のすべてのIValidationResults
がコレクションに含まれますが、カウントには含まれないようにします。私はそれが奇妙に聞こえることを知っていますが、xエラー後にファイルの検証を続ける必要はありませんが、検証によって無限の "警告"が返される可能性があります。
CPUが重いので、列挙型が複数回列挙されないようにすることが非常に重要です。以下は変更したいコードです。
private IEnumerable<IValidationResult> Validate(IDeliveryObject deliveryObject)
{
var validationErrors = new List<IValidationResult>();
int maxNumberOfErrors = 10;
foreach (IDeliveryValidator deliveryValidator in _validators)
{
// Here I want results to contain MAX 10 regular validation results, but unlimited soft validation results
IEnumerable<IValidationResult> results = deliveryValidator.Validate(deliveryObject).Take(maxNumberOfErrors);
validationErrors.AddRange(results);
if (validationErrors.Count(x => !x.IsSoftError) >= maxNumberOfErrors)
{
return validationErrors.Take(maxNumberOfErrors).ToList();
}
}
return validationErrors;
}
EDIT: 私は10 'ハード' エラーを得たとき、私は完全にサイクルを停止したいです。ここでの主な問題は、「ソフトエラー」が発生したときにサイクルが停止しないことです。あなたは完全に10「ハード」エラーの後に停止したい場合は
バリデータごとに非ソフトエラーを最大10個持ちますか?または全体的に? –
すべてのソフトエラーを取得したい場合。たとえあなたがソフトではない10のエラーに達したとしても、最後まで列挙しなければなりません。つまり、最終結果をフィルタリングするだけで済みます。 100の非ソフトエラーが発生した後、ソフトエラーが発生する可能性があります。 –
実際は全体的です。しかし、私が今使っている解決策は、合計を追跡して各バリデーターに10個のエラーを追加するところではまだ動作しています。それが10 + 10ならそれほど重要ではありません。 – smoksnes