-
Notifications
You must be signed in to change notification settings - Fork 68
Home
Start by creating a new project of your chosing and install the peasy nuget package.
Next create a domain object (DTO) that implements IDomainObject<T>
:
using Peasy;
public class Person : IDomainObject<int>
{
public int ID { get; set; }
public string Name { get; set; }
public string City { get; set; }
public int Age { get; set; }
}
Then create a data proxy (aka repository) that implements IDataProxy<T, TKey>
(most methods not implemented for brevity):
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Peasy;
namespace samples
{
public class PersonStubDataProxy : IDataProxy<Person, int>
{
public Task<IEnumerable<Person>> GetAllAsync()
{
return Task.FromResult<IEnumerable<Person>>
(
new []
{
new Person() { ID = 1, Name = "Jimi Hendrix" },
new Person() { ID = 2, Name = "James Page" },
new Person() { ID = 3, Name = "David Gilmour" }
}
);
}
public Task<Person> InsertAsync(Person entity)
{
return Task.FromResult(new Person() { ID = new Random(300).Next(), Name = entity.Name });
}
public Task DeleteAsync(int id)
{
throw new NotImplementedException();
}
public Task<Person> GetByIDAsync(int id)
{
throw new NotImplementedException();
}
public Task<Person> UpdateAsync(Person entity)
{
throw new NotImplementedException();
}
}
}
Finally, create a service class, which exposes CRUD commands responsible for subjecting IDataProxy invocations to business rules before execution:
using Peasy;
public class PersonService : ServiceBase<Person, int>
{
public PersonService(IDataProxy<Person, int> dataProxy) : base(dataProxy)
{
}
}
Now let's consume our PersonService:
var service = new PersonService(new PersonStubDataProxy());
var getResult = await service.GetAllCommand().ExecuteAsync();
if (getResult.Success)
{
foreach (var person in getResult.Value)
Debug.WriteLine(person.Name); // prints each person's name retrieved from PersonMockDataProxy.GetAll
}
var newPerson = new Person() { Name = "Erlich Bachman", City = "Madison", Age = 32 };
var insertResult = await service.InsertCommand(newPerson).ExecuteAsync();
if (insertResult.Success)
{
Debug.WriteLine(insertResult.Value.ID.ToString()); // prints the id value assigned via PersonMockDataProxy.Insert
}
Let's create a business rule whose execution must be successful before the call to IDataProxy.InsertAsync is invoked
using System.Threading.Tasks;
using Peasy;
public class ValidAgeRule : RuleBase
{
private int _age;
public ValidAgeRule(int age)
{
_age = age;
}
protected override Task OnValidateAsync()
{
return IfNot(() => _age >= 21)
.ThenInvalidateWith("You are not old enough");
// You can use this syntax too if you prefer:
// if (_age < 21)
// {
// Invalidate("You are not old enough");
// }
// return Task.CompletedTask;
}
}
And wire it up in our PersonService to ensure that it gets fired before inserts:
using System.Collections.Generic;
using System.Threading.Tasks;
using Peasy;
using Peasy.Extensions;
public class PersonService : ServiceBase<Person, int>
{
public PersonService(IDataProxy<Person, int> dataProxy) : base(dataProxy)
{
}
protected override Task<IEnumerable<IRule>> OnInsertCommandGetRulesAsync(Person resource, ExecutionContext<Person> context)
{
return TheseRules(new ValidAgeRule(resource.Age));
// You can use this syntax too if you prefer:
// return Task.FromResult(new ValidAgeRule(resource.Age).ToArray());
}
}
Testing it out:
var service = new PersonService(new PersonStubDataProxy());
var newPerson = new Person() { Name = "Erlich Bachman", City = "Madison", Age = 18 };
var insertResult = await service.InsertCommand(newPerson).ExecuteAsync();
if (insertResult.Success)
{
Debug.WriteLine(insertResult.Value.ID.ToString());
}
else
{
// This line will execute and print 'You are not old enough'
// Note that insertResult.Value will be NULL as PersonStubDataProxy.Insert did not execute due to failed rule
Debug.WriteLine(insertResult.Errors.First());
}
Let's create one more rule, just for fun:
using System.Threading.Tasks;
using Peasy;
public class ValidCityRule : RuleBase
{
private string _city;
public ValidCityRule(string city)
{
_city = city;
}
protected override Task OnValidateAsync()
{
return If(() => _city == "Nowhere")
.ThenInvalidateWith("Nowhere is not a city");
// You can use this syntax too if you prefer:
// if (_city == "Nowhere")
// {
// Invalidate("Nowhere is not a city");
// }
// return Task.CompletedTask;
}
}
We'll associate this one with inserts too:
using System.Collections.Generic;
using System.Threading.Tasks;
using Peasy;
public class PersonService : ServiceBase<Person, int>
{
public PersonService(IDataProxy<Person, int> dataProxy) : base(dataProxy)
{
}
protected override Task<IEnumerable<IRule>> OnInsertCommandGetRulesAsync(Person resource, ExecutionContext<Person> context)
{
return TheseRules
(
new ValidAgeRule(resource.Age),
new ValidCityRule(resource.City)
);
// You can use syntax like this too if you prefer:
// return Task.FromResult<IEnumerable<IRule>>(new IRule[]
// {
// new ValidAgeRule(resource.Age),
// new ValidCityRule(resource.City)
// });
}
}
And test it out:
var service = new PersonService(new PersonStubDataProxy());
var newPerson = new Person() { Name = "Erlich Bachman", City = "Nowhere", Age = 18 };
var insertResult = await service.InsertCommand(newPerson).ExecuteAsync();
if (insertResult.Success)
{
Debug.WriteLine(insertResult.Value.ID.ToString());
}
else
{
// This line will execute and print 'You are not old enough' and 'Nowhere is not a city'
// Note that insertResult.Value will be NULL as PersonStubDataProxy.Insert did not execute due to failed rule
foreach (var error in insertResult.Errors)
Debug.WriteLine(error);
}
Finally, let's supply valid data and watch it be a success
var service = new PersonService(new PersonStubDataProxy());
var newPerson = new Person() { Name = "Erlich Bachman", City = "Madison", Age = 21 };
var insertResult = await service.InsertCommand(newPerson).ExecuteAsync();
if (insertResult.Success)
{
Debug.WriteLine(insertResult.Value.ID.ToString()); // prints the id value assigned via PersonStubDataProxy.Insert
}
else
{
foreach (var error in insertResult.Errors)
Debug.WriteLine(error);
}