-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathContractValidation.cs
112 lines (97 loc) · 3.28 KB
/
ContractValidation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using Daktela.HttpClient.Attributes;
using Daktela.HttpClient.Interfaces;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
namespace Daktela.HttpClient.Implementations;
public class ContractValidation : IContractValidation
{
public ValidationResult? Validate<
[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicFields |
DynamicallyAccessedMemberTypes.PublicProperties
)]
TContract
>(TContract contract, EOperation operation)
where TContract : class
{
var type = typeof(TContract);
var errors = new List<string>();
foreach (var memberInfo in GetMembers(type))
{
var daktelaRequirementAttributes = memberInfo.GetCustomAttributes()
.OfType<DaktelaRequirementAttribute>()
.Where(x => x.ApplyOnOperation.HasFlag(operation));
foreach (var daktelaRequirementAttribute in daktelaRequirementAttributes)
{
Validate(contract, memberInfo, daktelaRequirementAttribute, errors);
}
}
if (errors.Any())
{
return new ValidationResult("Following members are required:", errors);
}
return ValidationResult.Success;
}
private void Validate<TContract>(
TContract contract,
MemberInfo memberInfo,
DaktelaRequirementAttribute attribute,
ICollection<string> errors
) where TContract : class
{
var (value, memberType) = memberInfo switch
{
FieldInfo fieldInfo => (fieldInfo.GetValue(contract), fieldInfo.FieldType),
PropertyInfo propertyInfo => (propertyInfo.GetValue(contract), propertyInfo.PropertyType),
_ => throw new ArgumentOutOfRangeException(nameof(memberInfo.MemberType), memberInfo.MemberType, null),
};
if (memberType.IsEnum && value is not null)
{
return;
}
switch (attribute)
{
case DaktelaNonZeroValueAttribute daktelaNonZeroValueAttribute:
if (daktelaNonZeroValueAttribute.IsValid(value))
{
return;
}
errors.Add(memberInfo.Name);
return;
}
switch (value)
{
case null:
errors.Add(memberInfo.Name);
break;
case string stringValue:
if (string.IsNullOrEmpty(stringValue))
{
errors.Add(memberInfo.Name);
}
break;
default:
throw new NotSupportedException($"The {nameof(value)} type {value.GetType()} is not supported");
}
}
private IEnumerable<MemberInfo> GetMembers(
[DynamicallyAccessedMembers(
DynamicallyAccessedMemberTypes.PublicFields |
DynamicallyAccessedMemberTypes.PublicProperties
)]
Type type)
{
foreach (var fieldInfo in type.GetFields())
{
yield return fieldInfo;
}
foreach (var propertyInfo in type.GetProperties())
{
yield return propertyInfo;
}
}
}