View on GitHub

TypeLess

More code - Less typing

Download this project as a .zip file Download this project as a tar.gz file

No dependencies | Portal library | Easy to extend with your own validations

Available on nuget: PM> Install-Package TypeLess

What problem/annoyance is this trying to solve

public void Login(SomeDTO data) {
    if (data == null) {
        throw new ArgumentNullException("Data is required");
    }

    if (data.Email == null) {
        throw new ArgumentNullException("Email is required");
    }

    if (NotValidEmail(data.Email)) {
        throw new ArgumentException("Email is not valid");
    }

    if (data.Email.Length > 5) {
        throw new ArgumentException("Email must be shorter than 6 characters")
    }

    ...
}

If you are like me then writing that is tedious!

Would be easier to write this

using TypeLess;
...
public SomeMethod(SomeDTO input)
{
    input.If("Input").IsNull.ThenThrow();
    input.Email.If("Email").IsNull.IsNotValidEmail.ThenThrow();
    input.Name.If("Name").IsNull.IsEmptyOrWhitespace.ThenThrow();
    input.UserId.If("User id").IsSmallerThan(0).ThenThrow();

    ...
}

Or if you prefer to put validation in the class where it belongs

using TypeLess;
...
public class SomeDTO {
    public string Name { get; set; }
    public string Email { get; set; }
    public int UserId { get; set; }

    public ObjectAssertion IsInvalid() {
        return ObjectAssertion.New(
            Name.If().IsNull.IsNotValidEmail,
            Email.If().IsNull.IsEmptyOrWhitespace,
            UserId.If().IsSmallerThan(0));
    }
}

...

public void Login(SomeDTO input)
{
    input.If().IsInvalid.ThenThrow();
}

How about this case?

s1.If("s1").IsNull.ThenThrow();
s2.If("s2").IsNull.ThenThrow();
s3.If("s3").IsNull.ThenThrow();

If you need to check the same predicates on multiple objects like above then you can do this

s1.If("s1").Or(s2, "s2").Or(s3, "s3").IsNull.ThenThrow().Otherwise(() => {...});

If you need to you can also group different types like this

string s1 = "some string";
double d1 = 0;
s1.If("s1").IsNull.Or(d1.If("d1").IsGreaterThan(0)).ThenThrow();

And of course you can use multiple checks as in the very unreal example below

d1.If("1").Or(d2, "2").Or(d3, "3").IsSmallerThan(5).IsGreaterThan(0).ThenThrow();

And that is what you do with TypeLess! Nothing more, nothing (but hopefully) less

Example of output:

string email = "some text";
email.If("Email")
  .IsNull
  .IsNotValidEmail
  .IsLongerThan(5).ThenThrow();

or if the parameter name is not important in the exception output you can leave it out

email.If().IsNull.IsNotValidEmail.ThenThrow();

here is how you use custom error message (you can use <name> anywhere in the text to include the parameter name)

email.If("email").IsNull.IsNotValidEmail.ThenThrow("<name> was not a valid email address");

and of course you can throw custom exceptions

email.If("email").IsNull.IsNotValidEmail.ThenThrow<SomeException>("<name> was not a valid email address");

Use with normal if statement

var precondition = email.If().IsNull.IsNotValidEmail;
if (!precondition.True) {
    //Get errors
    string errors = precondition.ToString();
}

Another if statement example

var angle = 345;

if (angle.If()
 .IsWithin(315, 360)
 .Or(angle).IsWithin(0, 45)
 .Or(angle).IsWithin(135, 225).True) 
{
 ...
}
else {...}

or this would produce the same results

if (angle.If()
 .IsWithin(315, 360)
 .IsWithin(0, 45)
 .IsWithin(135, 225).True) 
{
 ...
}
else {...}

or

angle.If()
 .IsWithin(315, 360)
 .IsWithin(0, 45)
 .IsWithin(135, 225).Then(a => {...}).Otherwise(a => {...});

Custom validation with lambda expresions

double a=1.0,b=2.0,c=3.0;
a.If().IsFalse(x => x > b && x < c, "a must be between b and c").ThenThrow();

Short circuit validation (default for isNull check)

string email = "some text";
  email.If("Email")
    .IsNotValidEmail.StopIfNotValid
    .IsLongerThan(5).ThenThrow();

Combine validations from multiple assertions with custom separator

DateTime d1 = new DateTime(2014,05,01);
DateTime d2 = new DateTime(2014,05,10);
string s1 = "abc";

var ifDateNotValid = new DateTime(2014, 05, 24).If().IsNotWithin(d1, d2);
var ifStringNotValid = s1.If("abc").IsShorterThan(4);

ifDateNotValid.Or(ifStringNotValid, "<br />").ThenThrow();

How to add your own validation code on top of TypeLess

Adding your own checks is easy. Just create an extension method for the assertion type you are interested in like this

public static class PersonalNumber
{
    public static IStringAssertion IsNotValidPersonalNumber(this IStringAssertionU source) {
        source.Extend(x =>
        {
            return AssertResult.New(!Luhn.IsValid(x.ToIntArray()), Resources.IsNotValidPersonalNumber);
        });
        return (IStringAssertion)source;
    }
}

This method extends the IStringAssertionU interface with a swedish personal number check for strings according to the Luhn algorithm. Note the U at the end of the interface and that it is not included in the return type. This is simply because the method should be available directly after the If() statement and not only after other assertions have been made. The Extend method will not show up in code completion but its there and it expects a function that receives the string (value) being checked and returns an AssertResult that takes the condition followed by the error message. Use <name> in the error message for replacement with parameter name

The following types can be extended

Features:

Available (predefined) checks:

Extensions

The framework target profile supports