Forked from olivier5741/FluentValidationAlternative.cs
Created
January 8, 2024 09:42
-
-
Save ntxinh/8c8002b322768137caaa48ac47dcb50d to your computer and use it in GitHub Desktop.
Revisions
-
olivier5741 revised this gist
Nov 8, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,7 +14,7 @@ public class UserValidator : IValidator<User> { public void Validate(RuleSet<User> r) { r += u => u.Age > 0; // TODO : recognise expression and select "greater than" message pattern r += u => (u.Name != null, when: u.Age >= 1, "You should have a name if you are 1 or older"); r += u => (u.Name == "test", "Name should be equal to test"); } -
olivier5741 revised this gist
Nov 8, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,7 +14,7 @@ public class UserValidator : IValidator<User> { public void Validate(RuleSet<User> r) { r += u => u.Age > 0; // TODO : recognise expression and select greater than pattern r += u => (u.Name != null, when: u.Age >= 1, "You should have a name if you are 1 or older"); r += u => (u.Name == "test", "Name should be equal to test"); } -
olivier5741 revised this gist
Nov 8, 2018 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,7 +14,7 @@ public class UserValidator : IValidator<User> { public void Validate(RuleSet<User> r) { r += u => u.Age > 0; r += u => (u.Name != null, when: u.Age >= 1, "You should have a name if you are 1 or older"); r += u => (u.Name == "test", "Name should be equal to test"); } -
olivier5741 revised this gist
Nov 8, 2018 . 1 changed file with 98 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,14 +7,16 @@ namespace Validation.Tests public class User { public string Name { get; set; } public int Age { get; set; } } public class UserValidator : IValidator<User> { public void Validate(RuleSet<User> r) { r += u => (u.Age > 0); r += u => (u.Name != null, when: u.Age >= 1, "You should have a name if you are 1 or older"); r += u => (u.Name == "test", "Name should be equal to test"); } } @@ -31,10 +33,18 @@ public void PocoValidation() { }); Assert.Equal(emptyName[0], "There is an error"); var nameRequired = factory.Validate(new User { Age = 2 }); Assert.Equal(nameRequired[0], "You should have a name if you are 1 or older"); var wrongName = factory.Validate(new User { Age = 2, Name = "wrong" }); @@ -59,25 +69,102 @@ public List<string> Validate<T>(T poco) var messages = new List<string>(); foreach (var rule in ruleSet.Rules) { bool validate; var message = "There is an error"; var when = true; switch (rule.Type) { case RuleTypes.Simple: (validate) = rule.RuleSimple.Invoke(poco); break; case RuleTypes.WithMessage: (validate, message) = rule.RuleWithMessage.Invoke(poco); break; case RuleTypes.When: (validate, when) = rule.RuleWhen.Invoke(poco); break; case RuleTypes.WhenWithMessage: (validate, when, message) = rule.RuleWhenWithMessage.Invoke(poco); break; default: throw new ArgumentOutOfRangeException(); } if (when && validate == false) messages.Add(message); } return messages; } } public delegate (bool validate, string message) RuleWithMessage<in T>(T poco); public delegate (bool validate, bool when) RuleWhen<in T>(T poco); public delegate (bool validate, bool when, string message) RuleWhenWithMessage<in T>(T poco); public delegate bool RuleSimple<in T>(T poco); public enum RuleTypes { Simple, WithMessage, When, WhenWithMessage } public class Rule<T> { public RuleTypes Type { get; set; } public RuleSimple<T> RuleSimple { get; set; } public RuleWithMessage<T> RuleWithMessage { get; set; } public RuleWhen<T> RuleWhen { get; set; } public RuleWhenWithMessage<T> RuleWhenWithMessage { get; set; } } public class RuleSet<T> { public List<Rule<T>> Rules { get; set; } = new List<Rule<T>> (); public static RuleSet<T> operator +(RuleSet<T> a, RuleWithMessage<T> b) { a.Rules.Add(new Rule<T> { Type = RuleTypes.WithMessage, RuleWithMessage = b.Invoke }); return a; } public static RuleSet<T> operator +(RuleSet<T> a, RuleSimple<T> b) { a.Rules.Add(new Rule<T> { Type = RuleTypes.Simple, RuleSimple = b.Invoke }); return a; } public static RuleSet<T> operator +(RuleSet<T> a, RuleWhen<T> b) { a.Rules.Add(new Rule<T> { Type = RuleTypes.When, RuleWhen = b.Invoke }); return a; } public static RuleSet<T> operator +(RuleSet<T> a, RuleWhenWithMessage<T> b) { a.Rules.Add(new Rule<T> { Type = RuleTypes.WhenWithMessage, RuleWhenWithMessage = b.Invoke }); return a; } } -
olivier5741 revised this gist
Nov 8, 2018 . 1 changed file with 38 additions and 39 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,9 +1,14 @@ namespace Validation.Tests { using System; using System.Collections.Generic; using Xunit; public class User { public string Name { get; set; } } public class UserValidator : IValidator<User> { public void Validate(RuleSet<User> r) @@ -12,11 +17,35 @@ public void Validate(RuleSet<User> r) r += u => (u.Name != null && u.Name == "test", "Name should be equal to test"); } } public class ValidationTest { [Fact] public void PocoValidation() { var factory = new ValidatorFactory(); factory.Register(new UserValidator()); var emptyName = factory.Validate(new User { }); Assert.Equal(emptyName[0], "Name should not be empty"); var wrongName = factory.Validate(new User { Name = "wrong" }); Assert.Equal(wrongName[0], "Name should be equal to test"); } } public class ValidatorFactory { public Dictionary<Type, object> Validators { get; set; } = new Dictionary<Type, object>(); public void Register<T>(IValidator<T> validator) { var ruleSet = new RuleSet<T>(); @@ -27,14 +56,14 @@ public void Register<T>(IValidator<T> validator) public List<string> Validate<T>(T poco) { var ruleSet = (RuleSet<T>) Validators[typeof(T)]; var messages = new List<string>(); foreach (var rule in ruleSet) { var (result, message) = rule.Invoke(poco); if (result == false) messages.Add(message); } @@ -43,7 +72,7 @@ public List<string> Validate<T>(T poco) } public delegate (bool validate, string message) Rule<in T>(T poco); public class RuleSet<T> : List<Rule<T>> { public static RuleSet<T> operator +(RuleSet<T> a, Rule<T> b) @@ -55,40 +84,10 @@ public class RuleSet<T> : List<Rule<T>> public interface IValidator { } public interface IValidator<T> : IValidator { void Validate(RuleSet<T> r); } } -
olivier5741 created this gist
Nov 8, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,94 @@ using System; using System.Collections.Generic; using Xunit; namespace Validation.Tests { public class UserValidator : IValidator<User> { public void Validate(RuleSet<User> r) { r += u => (u.Name != null, "Name should not be empty"); r += u => (u.Name != null && u.Name == "test", "Name should be equal to test"); } } public class ValidatorFactory { public Dictionary<Type, object> Validators { get; set; } = new Dictionary<Type, object>(); public void Register<T>(IValidator<T> validator) { var ruleSet = new RuleSet<T>(); validator.Validate(ruleSet); Validators.Add(typeof(T), ruleSet); } public List<string> Validate<T>(T poco) { var ruleSet = (RuleSet<T>) Validators[typeof(T)]; var messages = new List<string>(); foreach (var rule in ruleSet) { var (result, message) = rule.Invoke(poco); if(result == false) messages.Add(message); } return messages; } } public delegate (bool validate, string message) Rule<in T>(T poco); public class RuleSet<T> : List<Rule<T>> { public static RuleSet<T> operator +(RuleSet<T> a, Rule<T> b) { a.Add(b); return a; } } public interface IValidator { } public interface IValidator<T> : IValidator { void Validate(RuleSet<T> r); } public class User { public string Name { get; set; } } public class ValidationTest { [Fact] public void PocoValidation() { var factory = new ValidatorFactory(); factory.Register(new UserValidator()); var emptyName = factory.Validate(new User { }); Assert.Equal(emptyName[0], "Name should not be empty"); var wrongName = factory.Validate(new User { Name = "wrong" }); Assert.Equal(wrongName[0], "Name should be equal to test"); } } }