The features of “Bouncer”

As described in the last two posts, I’ve implemented a validation engine for method arguments. I know there are already some – but this one might be different. What you get is:

1 ) simple synthax:

public void CheckCustomer(
    string customerId,
    int amount,
    MyCustomer theCustomer)
{
    var results = Bouncer
        .ForCheckData(() => customerId)
        .ForCheckData(() => amount)
        .ForCheckData(() => theCustomer)
        .Assert();

    Util.PrintEntries(results);
}

In this example we are checking the three method arguments. For additional parameters, you parameters, you simply add a ForCheckData-statement.

2 ) higly customizable:

Bouncer
    .ForCheckData(() => customer)
    .Assert(new RuleBase<MyCustomer, object>
        {
            Message = "Sven cannot enter this method",
            CheckExpression = (x, y) => x.FullName != "Sven"
        });

This code will check the property “FillName” for not being equal to “Sven”. As you can see, the custom rule is a new instance of the generic rule RuleBase – you simply can inherit from that rule and build you own reusable rule:

internal class CanNotEnterRule
               : RuleBase<MyCustomer, object>
{
    public CanNotEnterRule()
    {
        this.Message = "Sven cannot enter this method";
        this.CheckExpression = (x, y) => x.FullName != "Sven";
    }
}

That’s a complete rule – the expression can be as complex as you want.

3 ) descriptive error messages:
The rule Sem.GenericHelpers.Contracts.Rules.IsNotNullRule`1 did fail for value name >>customer.InternalId<<: The object is NULL.
Parameter name: customer.InternalId
This is an “out of the box” exception message for an argument that should not be null, but is null … that’s a bit more helpful than an “Object not set to a reference of an object”.

4 ) Bundeling and reusage of rules:

internal class StrictCustomerCheckRuleSet
             : RuleSet<MyCustomer, object>
{
    protected override IEnumerable<RuleBase<MyCustomer, object>> GetRuleList()
    {
        var ruleset = new List<RuleBase<MyCustomer, object>>
            {
                new IsNotNullRule<MyCustomer>(),
                new CanNotEnterRule(),
            };

        return ruleset;
    }
}

This is a rule set – a set of two rules that have been combined, so you can add more checks with different messages without duplicating code all over your project.

5 ) declarative rules:

[MethodRule(typeof(IntegerLowerThanRule), "amount", Parameter = 100)]
[MethodRule(typeof(StringNotNullOrEmptyRule), "customerId")]
public void CheckCustomer(
       string customerId,
       int amount,
       MyCustomer theCustomer)
{
    Bouncer
        .ForCheckData(() => customerId)
        .ForCheckData(() => amount)
        .ForCheckData(() => theCustomer)
        .Assert();

This method declares via attributes that theCustomer should be checked for not being null and amount be lower than 100. This can be done via a rule set, too, so you can change the rules for multiple methods in one location:

[MethodRule(typeof(StrictCustomerCheckRuleSet), "customer")]
internal void InsertCustomer(MyCustomer customer)
{
    Bouncer.ForCheckData(() => customer).Assert();

6 ) declaration at the entity level:
Rules can be attached to classes and properties of classes, so you can define, that a Customer always must have a valid customer ID.

7 ) declaration of validation “context”:
Some class-attached rules should be evaluated only in special areas of the application. You can restrict the rule to a specific namespace or a string that you attache to the “code execution unit” – the method or class that uses that entity:

[ContractContext("Create")]
[ContractContext("Read", false)]
[MethodRule(typeof(StrictCustomerCheckRuleSet), "customer")]
internal void InsertCustomer(MyCustomer customer)
{
    var results = Bouncer.ForMessages(() => customer).Assert();

In this example the method is running in the context “Create” – the context “Read” (which is set on Class level) is explicitly switched off. In the example code this method does virtually create a customer, so the customer ID cannot be set in the customer instance passed to that method. The rule for checking the customer id to be set is actiove for the context “Read”, but for “Create” a different rule has been declared that ensures the customer id not to be set.

8 ) testing if a rule would be violated without throwing exceptions:

    var results = Bouncer.ForMessages(() => customer).Assert();

This line does query the validation engine for the rules that this instance of customer does violate.

9 ) central logging of rule violation/execution
There’s a list of Action, which will be executed each time a rule has been validated. You can filter there for interesting rules/results and log the results.
You can attach to this from everywhere in your code.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Sylvio's Infobox

Aktuelle Themen rund um SQL Server, BI, Windows, ...

Meredith Lewis

Professional Digital Portfolio

Vittorio Bertocci

Just another WordPress.com weblog

ScottGu's Blog

Just another WordPress.com weblog

AJ's blog

Thoughts and informations I think worthwhile to share...

Outlawtrail - .NET Development

Architecture & Design

SDX eXperts Flurfunk

Just another WordPress.com weblog

%d bloggers like this: