using System.Collections;
using System.Collections.Generic;
public static void Main()
var dict = new ValidationResultErrors<IValidationResultErrorIdentifier>();
ValidationResultTimesheetIdentifier nullIdentifier = null;
dict.AddError(nullIdentifier, "blah");
catch (ArgumentNullException)
Console.WriteLine($"{Environment.NewLine}caught");
var identifier = new ValidationResultTimesheetIdentifier(1, null);
dict.AddError(identifier, "foo");
dict.AddError(identifier, "foo2");
Console.WriteLine($"{Environment.NewLine}Keys: {dict.Keys.Count}");
Console.WriteLine($"Values: {string.Join(",", dict.Values.ToList()[0])}");
var identifier2 = new ValidationResultTimesheetDetailIdentifier(1, 1, null);
dict.AddError(identifier2, "bar");
dict.AddError(identifier2, "bar2");
Console.WriteLine($"{Environment.NewLine}Keys: {dict.Keys.Count}");
Console.WriteLine($"Values: {string.Join(",", dict.Values.ToList()[1])}");
if (kvp.Key is ValidationResultTimesheetIdentifier)
Console.WriteLine("Type: ValidationResultTimesheetIdentifier");
else if (kvp.Key is ValidationResultTimesheetDetailIdentifier)
Console.WriteLine("Type: ValidationResultTimesheetDetailIdentifier");
public abstract class ValidationResultBase
public ValidationResultStatus Status { get; set; } = ValidationResultStatus.Inconclusive;
public Exception Exception { get; set; }
public abstract IValidationResultErrors Errors { protected get; set; }
public virtual TValidationResultErrors GetErrors<TValidationResultErrors>()
where TValidationResultErrors : class, IValidationResultErrors
return Errors as TValidationResultErrors;
public class ValidationResult : ValidationResultBase
public override IValidationResultErrors Errors { protected get; set; }
= new ValidationResultErrors<string>(StringComparer.InvariantCultureIgnoreCase);
public virtual ValidationResultErrors<string> GetErrors() =>
GetErrors<ValidationResultErrors<string>>();
public class ValidationResult<TErrorIdentifier>: ValidationResultBase
public override IValidationResultErrors Errors { protected get; set; }
= new ValidationResultErrors<TErrorIdentifier>();
public interface IValidationResultErrors: IDictionary
public class ValidationResultErrors<TErrorIdentifier> : Dictionary<TErrorIdentifier, List<string>>, IValidationResultErrors
public ValidationResultErrors() : base()
public ValidationResultErrors(IEqualityComparer<TErrorIdentifier> comparer) : base(comparer)
public virtual void AddError(TErrorIdentifier key, string value)
throw new ArgumentNullException(nameof(key));
Add(key, new List<string>());
this[key] = new List<string>();
public class ValidationResultTimesheetErrors: ValidationResultErrors<ValidationResultTimesheetIdentifier>{}
public class ValidationResultTimesheetDetailErrors: ValidationResultErrors<ValidationResultTimesheetDetailIdentifier>{}
public interface IValidationResultErrorIdentifier
public class ValidationResultTimesheetIdentifier :
IEquatable<ValidationResultTimesheetIdentifier>, IValidationResultErrorIdentifier
public long TimesheetSummaryId { get; }
public string Property { get; }
public ValidationResultTimesheetIdentifier(long timesheetId, string property = "")
TimesheetSummaryId = timesheetId;
Property = property ?? "";
public override bool Equals(object obj) =>
obj is ValidationResultTimesheetIdentifier other && this.Equals(other);
public bool Equals(ValidationResultTimesheetIdentifier p) =>
TimesheetSummaryId == p.TimesheetSummaryId
&& Property == p.Property;
public override int GetHashCode() => (TimesheetSummaryId, Property).GetHashCode();
public static bool operator ==(ValidationResultTimesheetIdentifier lhs, ValidationResultTimesheetIdentifier rhs) => !(lhs == null) && lhs.Equals(rhs);
public static bool operator !=(ValidationResultTimesheetIdentifier lhs, ValidationResultTimesheetIdentifier rhs) => !(lhs == rhs);
public class ValidationResultTimesheetDetailIdentifier :
IEquatable<ValidationResultTimesheetDetailIdentifier>, IValidationResultErrorIdentifier
public long TimesheetSummaryId { get; }
public long TimesheetDetailId { get; }
public string Property { get; }
public ValidationResultTimesheetDetailIdentifier(long timesheetId, long timesheetDetailId, string property = "")
TimesheetSummaryId = timesheetId;
TimesheetDetailId = timesheetDetailId;
Property = property ?? "";
public override bool Equals(object obj) =>
obj is ValidationResultTimesheetDetailIdentifier other && this.Equals(other);
public bool Equals(ValidationResultTimesheetDetailIdentifier p) =>
TimesheetSummaryId == p.TimesheetSummaryId
&& TimesheetDetailId == p.TimesheetDetailId
&& Property == p.Property;
public override int GetHashCode() => (TimesheetSummaryId, TimesheetDetailId, Property).GetHashCode();
public static bool operator ==(ValidationResultTimesheetDetailIdentifier lhs, ValidationResultTimesheetDetailIdentifier rhs) => !(lhs == null) && lhs.Equals(rhs);
public static bool operator !=(ValidationResultTimesheetDetailIdentifier lhs, ValidationResultTimesheetDetailIdentifier rhs) => !(lhs == rhs);
public enum ValidationResultStatus