Skip to content

Commit 6b3a684

Browse files
committed
Merge branch 'release/1.0.1' into production
2 parents cce0c19 + 279ff4f commit 6b3a684

10 files changed

Lines changed: 150 additions & 24 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ TestResult.formatted.xml
66
*.orig
77
.directory
88
packages/*/
9+
.vs/

CSF-Software-OSS.snk

596 Bytes
Binary file not shown.

CSF.Validation.Tests/CSF.Validation.Tests.csproj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<OutputType>Library</OutputType>
1010
<RootNamespace>CSF.Validation.Tests</RootNamespace>
1111
<AssemblyName>CSF.Validation.Tests</AssemblyName>
12-
<ReleaseVersion>1.0.0</ReleaseVersion>
12+
<ReleaseVersion>1.0.1</ReleaseVersion>
1313
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
1414
</PropertyGroup>
1515
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -36,16 +36,14 @@
3636
<Reference Include="System" />
3737
<Reference Include="nunit.framework">
3838
<HintPath>..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
39+
<Package>nunit</Package>
3940
</Reference>
4041
<Reference Include="Castle.Core">
4142
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
4243
</Reference>
4344
<Reference Include="Moq">
4445
<HintPath>..\packages\Moq.4.7.8\lib\net45\Moq.dll</HintPath>
4546
</Reference>
46-
<Reference Include="CSF.Reflection">
47-
<HintPath>..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll</HintPath>
48-
</Reference>
4947
<Reference Include="Ploeh.AutoFixture">
5048
<HintPath>..\packages\AutoFixture.3.50.2\lib\net40\Ploeh.AutoFixture.dll</HintPath>
5149
</Reference>
@@ -55,6 +53,12 @@
5553
<Reference Include="Ploeh.AutoFixture.AutoMoq">
5654
<HintPath>..\packages\AutoFixture.AutoMoq.3.50.2\lib\net40\Ploeh.AutoFixture.AutoMoq.dll</HintPath>
5755
</Reference>
56+
<Reference Include="CSF.Reflection">
57+
<HintPath>..\packages\CSF.Reflection.1.0.2\lib\net45\CSF.Reflection.dll</HintPath>
58+
</Reference>
59+
<Reference Include="CSF.Utils">
60+
<HintPath>..\packages\CSF.Utils.6.1.0\lib\net45\CSF.Utils.dll</HintPath>
61+
</Reference>
5862
</ItemGroup>
5963
<ItemGroup>
6064
<ProjectReference Include="..\CSF.Validation\CSF.Validation.csproj">

CSF.Validation.Tests/packages.config

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
<package id="AutoFixture.AutoMoq" version="3.50.2" targetFramework="net45" />
55
<package id="AutoFixture.NUnit3" version="3.50.2" targetFramework="net45" />
66
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
7-
<package id="CSF.Reflection" version="1.0.1" targetFramework="net45" />
7+
<package id="CSF.Reflection" version="1.0.2" targetFramework="net45" />
8+
<package id="CSF.Utils" version="6.1.0" targetFramework="net45" />
89
<package id="Moq" version="4.7.8" targetFramework="net45" />
910
<package id="NUnit" version="3.6.1" targetFramework="net45" />
1011
<package id="NUnit.ConsoleRunner" version="3.6.1" targetFramework="net45" />

CSF.Validation.sln

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,13 @@ Global
2525
GlobalSection(MonoDevelopProperties) = preSolution
2626
Policies = $0
2727
$0.TextStylePolicy = $1
28-
$1.FileWidth = 120
2928
$1.TabWidth = 2
3029
$1.IndentWidth = 2
3130
$1.NoTabsAfterNonTabs = True
32-
$1.inheritsSet = VisualStudio
33-
$1.inheritsScope = text/plain
3431
$1.scope = text/plain
32+
$1.TabsToSpaces = True
3533
$0.StandardHeader = $2
3634
$2.Text = @\n${FileName}\n \nAuthor:\n ${AuthorName} <${AuthorEmail}>\n\nCopyright (c) ${Year} ${CopyrightHolder}\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the "Software"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.
37-
$2.IncludeInNewFiles = True
3835
$0.DotNetNamingPolicy = $3
3936
$3.DirectoryNamespaceAssociation = PrefixedHierarchical
4037
$3.ResourceNamePolicy = FileName
@@ -166,6 +163,6 @@ Global
166163
$25.NamingStyle = PascalCase
167164
$25.IncludeInstanceMembers = True
168165
$25.IncludeStaticEntities = True
169-
version = 1.0.0
166+
version = 1.0.1
170167
EndGlobalSection
171168
EndGlobal

CSF.Validation/CSF.Validation.csproj

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
<RootNamespace>CSF.Validation</RootNamespace>
1111
<AssemblyName>CSF.Validation</AssemblyName>
1212
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13-
<ReleaseVersion>1.0.0</ReleaseVersion>
13+
<ReleaseVersion>1.0.1</ReleaseVersion>
14+
<SignAssembly>true</SignAssembly>
15+
<AssemblyOriginatorKeyFile>..\CSF-Software-OSS.snk</AssemblyOriginatorKeyFile>
1416
</PropertyGroup>
1517
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1618
<DebugSymbols>true</DebugSymbols>
@@ -35,11 +37,13 @@
3537
</PropertyGroup>
3638
<ItemGroup>
3739
<Reference Include="System" />
38-
<Reference Include="CSF.Utils">
39-
<HintPath>..\packages\CSF.Utils.6.0.0\lib\net45\CSF.Utils.dll</HintPath>
40-
</Reference>
4140
<Reference Include="CSF.Reflection">
42-
<HintPath>..\packages\CSF.Reflection.1.0.1\lib\net45\CSF.Reflection.dll</HintPath>
41+
<HintPath>..\packages\CSF.Reflection.1.0.2\lib\net45\CSF.Reflection.dll</HintPath>
42+
<Private>False</Private>
43+
</Reference>
44+
<Reference Include="CSF.Utils">
45+
<HintPath>..\packages\CSF.Utils.6.1.0\lib\net45\CSF.Utils.dll</HintPath>
46+
<Private>False</Private>
4347
</Reference>
4448
</ItemGroup>
4549
<ItemGroup>

CSF.Validation/CSF.Validation.nuspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>CSF.Validation</id>
5-
<version>1.0.0</version>
5+
<version>1.0.1</version>
66
<title>CSF.Validation</title>
77
<authors>CSF Software Ltd</authors>
88
<licenseUrl>https://opensource.org/licenses/MIT</licenseUrl>
@@ -11,8 +11,8 @@
1111
<description>A framework for business rule validation</description>
1212
<copyright>Copyright 2017</copyright>
1313
<dependencies>
14-
<dependency id="CSF.Utils" version="[6.0.0,7.0.0)" />
15-
<dependency id="CSF.Reflection" version="[1.0.1,2.0.0)" />
14+
<dependency id="CSF.Utils" version="[6.1.0,7.0.0)" />
15+
<dependency id="CSF.Reflection" version="[1.0.2,2.0.0)" />
1616
</dependencies>
1717
</metadata>
1818
<files>

CSF.Validation/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@
3939
[assembly: AssemblyConfiguration("Release")]
4040
#endif
4141

42-
[assembly: AssemblyVersion("1.0.0")]
42+
[assembly: AssemblyVersion("1.0.1")]
4343

CSF.Validation/packages.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3-
<package id="CSF.Reflection" version="1.0.1" targetFramework="net45" />
4-
<package id="CSF.Utils" version="6.0.0" targetFramework="net45" />
3+
<package id="CSF.Reflection" version="1.0.2" targetFramework="net45" />
4+
<package id="CSF.Utils" version="6.1.0" targetFramework="net45" />
55
</packages>

README.md

Lines changed: 122 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,128 @@
11
# CSF Validation
2-
Validation library, currently undergoing a rewrite from scratch.
2+
CSF.Validation is a business rule validation framework.
3+
It is intended for use within the business logic layer of your application.
34

4-
The previous version is not particularly fit for use, and this rewrite is not yet ready for use.
5+
## How this differs from other frameworks
6+
Many validation frameworks (such as [ASP.NET validation controls] or [.NET validation attributes]) are intended for validation which lies close to the user interface.
7+
This is evident in their design, for example the validation failure messages are defined along with the validation rule itself.
8+
The human-readable failure message is a presentation/UI concern and not directly related to the the pass/fail of the rule logic.
59

6-
### Continuous integration builds
10+
[ASP.NET validation controls]: https://msdn.microsoft.com/en-us/library/debza5t0.aspx
11+
[.NET validation attributes]: https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute(v=vs.110).aspx
12+
13+
CSF.Validation separates concerns appropriately so that each aspect of the validation process may be controlled separately.
14+
If you wanted a simple validator which you will (architecturally speaking) keep close to your UI, then this framework is probably not for you.
15+
16+
If you want a shared validation framework which will live in your business logic layer, validating requests which come from a wide variety of other layers then this might be what you are looking for.
17+
18+
## Usage
19+
The process of validating an object is:
20+
21+
1. Create a validation manifest, which lists the rules which are desired, along with their configurations
22+
2. Use a validator factory to create a validator from that manifest
23+
3. Use the validator to validate your object
24+
25+
At the first stage, there is a static type named `ManifestBuilder` which can help you with the creation of a validation manifest.
26+
It provides a fluent interface to add and configure rules in the manifest.
27+
28+
## Example
29+
Here is an example of usage, including the creation of your own custom validation rule:
30+
31+
```csharp
32+
// A simple object model which we are going to validate
33+
34+
public interface IDessert
35+
{
36+
string Name { get; }
37+
decimal UnitPrice { get; }
38+
}
39+
40+
public interface IPurchaseDessertRequest
41+
{
42+
IDessert DessertToPurchase { get; }
43+
decimal MoneyInWallet { get; }
44+
int DesiredQuantity { get;
45+
}
46+
47+
// A custom validator type
48+
49+
// using CSF.Validation.Rules;
50+
public class CanAffordDessertRule : Rule<IPurchaseDessertRequest>
51+
{
52+
protected override RuleOutcome GetOutcome(IPurchaseDessertRequest request)
53+
{
54+
if(request == null)
55+
return Success;
56+
57+
var totalCost = request.DessertToPurchase.UnitPrice * request.DesiredQuantity;
58+
if(totalCost > request.MoneyInWallet)
59+
return Failure;
60+
61+
return Success;
62+
}
63+
}
64+
65+
// Code to construct the validator for this
66+
67+
// using CSF.Validation;
68+
// using CSF.Validation.Manifest;
69+
// using CSF.Validation.Manifest.Fluent;
70+
// using CSF.Validation.Manifest.StockRules;
71+
public IValidator CreatePurchaseDessertRequestValidator()
72+
{
73+
var builder = ManifestBuilder.Create<IPurchaseDessertRequest>();
74+
75+
builder.AddRule<NotNullRule>();
76+
77+
builder.AddMemberRule<NotNullValueRule>(x => x.DessertToPurchase, c => {
78+
c.AddDependency<NotNullRule,IPurchaseDessertRequest>();
79+
});
80+
81+
builder.AddMemberRule<NumericRangeValueRule>(x => x.DesiredQuantity, c => {
82+
c.Configure(r => {
83+
r.Min = 1;
84+
});
85+
c.AddDependency<NotNullRule,IPurchaseDessertRequest>();
86+
});
87+
88+
builder.AddMemberRule<CanAffordDessertRule>(c => {
89+
c.AddDependency<NotNullValueRule,IPurchaseDessertRequest>(x => x.DessertToPurchase);
90+
c.AddDependency<NumericRangeValueRule,IPurchaseDessertRequest>(x => x.DesiredQuantity);
91+
});
92+
93+
var factory = new ValidatorFactory();
94+
return factory.GetValidator(builder.GetManifest());
95+
}
96+
97+
// We get our validation result
98+
99+
var validator = CreatePurchaseDessertRequestValidator();
100+
var request = GetPurchaseDessertRequest();
101+
var result = validator.Validate(request);
102+
```
103+
104+
This example creates a validator with four validation rules:
105+
106+
* A not-null rule ensures that the request is not null
107+
* A not-null member rule ensures that the **DessertToPurchase** property is not null
108+
* A numeric range rule ensures that the **DesiredQuantity** property is at least 1
109+
* A custom rule ensures that the buyer can afford their desserts
110+
111+
Note the use of `.Configure()` in the numeric range rule.
112+
When building a validation manifest you may configure parameters in each individual rule via property setters on that rule.
113+
114+
Additionally, note that most of the rules have dependencies.
115+
The way dependencies work is that a rule which carries a dependency will not be executed (it will be marked as *skipped due to dependency failure* in the results) if any of the rules it depends upon have failed.
116+
In the example above, there is no point executing any of the property rules if the request itself is `null`.
117+
There is also no way to get a meaningful result from the `CanAffordDessertRule` if either the dessert is `null` or if the desired quantity is less than one.
118+
119+
Dependencies will automatically form chains; if a dependency rule is skipped due to a dependency failure of its own then any rules depending upon it will also be skipped.
120+
121+
A validation result contains a list of every validation rule in the manifest and the outcome of every single rule.
122+
Rules which have an outcome of `Success` or `IntentionallySkipped` (used in advanced scenarios) should be considered OK to allow validation to pass.
123+
Any other outcome indicates a validation failure.
124+
125+
## Build status
7126
CI builds are configured via both Travis (for build & test on Linux/Mono) and AppVeyor (Windows/.NET).
8127
Below are links to the most recent build statuses for these two CI platforms.
9128

0 commit comments

Comments
 (0)