-
-
Save NDiiong/671668dc67d04c40848ce97deff812b4 to your computer and use it in GitHub Desktop.
Showing a proposed use of Guard with expression for static checks and correct name evaluation in exception messages
This file contains 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 characters
public static class Guard | |
{ | |
public static void NotNull<T>(Expression<Func<T>> notNullableExpression) where T : class | |
{ | |
var compliedExpression = notNullableExpression.Compile(); | |
if (compliedExpression() == null) | |
{ | |
var paramName = notNullableExpression.GetObjectNameGraph(); | |
throw new ArgumentNullException(paramName); | |
} | |
} | |
public static void NotNullOrWhiteSpace(Expression<Func<string>> notNullableExpression) | |
{ | |
var compliedExpression = notNullableExpression.Compile(); | |
if (string.IsNullOrWhiteSpace(compliedExpression())) | |
{ | |
var paramName = notNullableExpression.GetObjectNameGraph(); | |
throw new ArgumentException("Must not be null or empty/whitepsace string", paramName); | |
} | |
} | |
public static void Require<T>(Expression<Func<T>> notNullableExpression, Expression<Predicate<T>> predicate) where T : class | |
{ | |
var x = notNullableExpression.Compile(); | |
if (!predicate.Compile()((x()))) | |
{ | |
var paramName = notNullableExpression.GetObjectNameGraph(); | |
throw new ArgumentException("failed predicate : " + predicate.ToString(), paramName); | |
} | |
} | |
} | |
public static class PropertyNameEx | |
{ | |
public static string GetObjectNameGraph<T>(this Expression<Func<T>> propertyExpression) | |
{ | |
var lambda = propertyExpression as LambdaExpression; | |
if(lambda == null) | |
throw new Exception("Must be a LambdaExpression"); | |
return string.Concat(GetPropertyNames(lambda.Body).Intersperse(".")); | |
} | |
private static IEnumerable<string> GetPropertyNames(Expression expression) | |
{ | |
var memberExpression = expression as MemberExpression; | |
if (memberExpression == null) yield break; | |
var member = memberExpression.Member as MemberInfo;//Lambda syntax may make the initial value a field (in a closure i assume) | |
if (member == null) | |
{ | |
memberExpression.Member.Dump("Error"); | |
throw new Exception("Expression member is not a property or field accessor"); | |
} | |
foreach (var propertyName in GetPropertyNames(memberExpression.Expression)) | |
{ | |
yield return propertyName; | |
} | |
yield return member.Name; | |
} | |
private static IEnumerable<T> Intersperse<T>(this IEnumerable<T> items, T separator) | |
{ | |
var first = true; | |
foreach (var item in items) | |
{ | |
if (first) | |
first = false; | |
else | |
yield return separator; | |
yield return item; | |
} | |
} | |
} |
This file contains 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 characters
void Main() | |
{ | |
var message = new { Alpha = "A", Beta = (string)null, Gamma = new { Delta = "Hi"}}; | |
var messageConcrete = new TestObj(); | |
messageConcrete.Testy = "Franco"; | |
try{ | |
Guard.NotNull(()=>message); | |
Guard.NotNullOrWhiteSpace(()=>message.Gamma.Delta); | |
Guard.NotNull(()=>messageConcrete.Testy); | |
Guard.Require(()=>messageConcrete.Testy, t=> t == "Arnold");//abitary prdeicate | |
} | |
catch(Exception ex) | |
{ | |
ex.Dump(); | |
} | |
message = new { Alpha = "A", Beta = (string)null, Gamma = new { Delta = (string)null}}; | |
try | |
{ | |
Guard.NotNullOrWhiteSpace(()=>message.Gamma.Delta); | |
} | |
catch(Exception ex) | |
{ | |
ex.Dump(); | |
} | |
} | |
public class TestObj | |
{ | |
public string Testy;//fields work ok | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment