Skip to content

Commit 0b533a4

Browse files
committed
Initial commit.
0 parents  commit 0b533a4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2633
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.vs/
2+
.config/
3+
bin/
4+
obj/
5+
*.suo
6+
*.user

LICENSE

+373
Large diffs are not rendered by default.

LocalizedDataAnnotationsValidator.sln

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29505.145
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleApp", "SampleApp\SampleApp.csproj", "{847AF15A-2735-423A-B3E3-4AC7B4862B03}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LocalizedDataAnnotationsValidator", "LocalizedDataAnnotationsValidator\LocalizedDataAnnotationsValidator.csproj", "{984436AD-220F-4A56-B985-2B770C726268}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "README", "README", "{11807821-F687-4347-8BED-68F0DC2D7780}"
11+
ProjectSection(SolutionItems) = preProject
12+
LICENSE = LICENSE
13+
README.md = README.md
14+
EndProjectSection
15+
EndProject
16+
Global
17+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
18+
Debug|Any CPU = Debug|Any CPU
19+
Release|Any CPU = Release|Any CPU
20+
EndGlobalSection
21+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
22+
{847AF15A-2735-423A-B3E3-4AC7B4862B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{847AF15A-2735-423A-B3E3-4AC7B4862B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{847AF15A-2735-423A-B3E3-4AC7B4862B03}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{847AF15A-2735-423A-B3E3-4AC7B4862B03}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{984436AD-220F-4A56-B985-2B770C726268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{984436AD-220F-4A56-B985-2B770C726268}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{984436AD-220F-4A56-B985-2B770C726268}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{984436AD-220F-4A56-B985-2B770C726268}.Release|Any CPU.Build.0 = Release|Any CPU
30+
EndGlobalSection
31+
GlobalSection(SolutionProperties) = preSolution
32+
HideSolutionNode = FALSE
33+
EndGlobalSection
34+
GlobalSection(ExtensibilityGlobals) = postSolution
35+
SolutionGuid = {D6BFCA44-8414-4FD8-95D8-B571D04634A9}
36+
EndGlobalSection
37+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Reflection;
2+
3+
namespace Toolbelt.Blazor.Forms.Internals.Extensions
4+
{
5+
internal static class ReflectionExtensions
6+
{
7+
internal static bool IsPublic(this PropertyInfo p)
8+
{
9+
if (!(p.GetMethod != null) || !p.GetMethod.IsPublic)
10+
{
11+
if (p.SetMethod != null)
12+
{
13+
return p.SetMethod.IsPublic;
14+
}
15+
return false;
16+
}
17+
return true;
18+
}
19+
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using Microsoft.Extensions.Localization;
3+
4+
namespace Toolbelt.Blazor.Forms.Internals
5+
{
6+
internal class LocalizedValidationContext
7+
{
8+
internal IStringLocalizer Localizer { get; }
9+
10+
internal ValidationContext Context { get; }
11+
12+
internal LocalizedValidationContext(IStringLocalizer localizer, object instance)
13+
{
14+
Localizer = localizer;
15+
Context = new ValidationContext(instance);
16+
}
17+
18+
internal LocalizedValidationContext(IStringLocalizer localizer, ValidationContext context)
19+
{
20+
Localizer = localizer;
21+
Context = context;
22+
}
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Toolbelt.Blazor.Forms.Internals.ValidationAttributeStores
5+
{
6+
internal class PropertyStoreItem : StoreItem
7+
{
8+
internal Type PropertyType { get; }
9+
10+
internal PropertyStoreItem(Type propertyType, IEnumerable<Attribute> attributes) : base(attributes)
11+
{
12+
PropertyType = propertyType;
13+
}
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Linq;
5+
6+
namespace Toolbelt.Blazor.Forms.Internals.ValidationAttributeStores
7+
{
8+
internal class StoreItem
9+
{
10+
internal IEnumerable<ValidationAttribute> ValidationAttributes { get; }
11+
12+
internal DisplayAttribute DisplayAttribute { get; }
13+
14+
internal StoreItem(IEnumerable<Attribute> attributes)
15+
{
16+
ValidationAttributes = attributes.OfType<ValidationAttribute>();
17+
DisplayAttribute = attributes.OfType<DisplayAttribute>().SingleOrDefault();
18+
}
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using Toolbelt.Blazor.Forms.Internals.Extensions;
6+
7+
namespace Toolbelt.Blazor.Forms.Internals.ValidationAttributeStores
8+
{
9+
internal class TypeStoreItem : StoreItem
10+
{
11+
private readonly object _syncRoot = new object();
12+
13+
private readonly Type _type;
14+
15+
private Dictionary<string, PropertyStoreItem> _propertyStoreItems;
16+
17+
internal TypeStoreItem(Type type, IEnumerable<Attribute> attributes) : base(attributes)
18+
{
19+
_type = type;
20+
}
21+
22+
internal PropertyStoreItem GetPropertyStoreItem(string propertyName)
23+
{
24+
if (!TryGetPropertyStoreItem(propertyName, out var item)) throw new ArgumentException();
25+
return item;
26+
}
27+
28+
internal bool TryGetPropertyStoreItem(string propertyName, out PropertyStoreItem item)
29+
{
30+
if (_propertyStoreItems == null)
31+
{
32+
lock (_syncRoot)
33+
{
34+
if (_propertyStoreItems == null)
35+
{
36+
_propertyStoreItems = CreatePropertyStoreItems();
37+
}
38+
}
39+
}
40+
return _propertyStoreItems.TryGetValue(propertyName, out item);
41+
}
42+
43+
private Dictionary<string, PropertyStoreItem> CreatePropertyStoreItems()
44+
{
45+
var dictionary = new Dictionary<string, PropertyStoreItem>();
46+
var enumerable = _type.GetRuntimeProperties().Where(prop => prop.IsPublic() && !prop.GetIndexParameters().Any());
47+
foreach (var item in enumerable)
48+
{
49+
var value = new PropertyStoreItem(item.PropertyType, CustomAttributeExtensions.GetCustomAttributes(item, inherit: true));
50+
dictionary[item.Name] = value;
51+
}
52+
return dictionary;
53+
}
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Reflection;
5+
6+
namespace Toolbelt.Blazor.Forms.Internals.ValidationAttributeStores
7+
{
8+
internal class ValidationAttributeStore
9+
{
10+
internal static ValidationAttributeStore Instance { get; } = new ValidationAttributeStore();
11+
12+
private readonly Dictionary<Type, TypeStoreItem> _typeStoreItems = new Dictionary<Type, TypeStoreItem>();
13+
14+
internal IEnumerable<ValidationAttribute> GetTypeValidationAttributes(ValidationContext validationContext)
15+
{
16+
var typeStoreItem = GetTypeStoreItem(validationContext.ObjectType);
17+
return typeStoreItem.ValidationAttributes;
18+
}
19+
20+
private TypeStoreItem GetTypeStoreItem(Type type)
21+
{
22+
lock (_typeStoreItems)
23+
{
24+
if (!_typeStoreItems.TryGetValue(type, out var value))
25+
{
26+
var customAttributes = CustomAttributeExtensions.GetCustomAttributes(type, inherit: true);
27+
value = new TypeStoreItem(type, customAttributes);
28+
_typeStoreItems[type] = value;
29+
}
30+
return value;
31+
}
32+
}
33+
34+
internal IEnumerable<ValidationAttribute> GetPropertyValidationAttributes(ValidationContext validationContext)
35+
{
36+
var typeStoreItem = GetTypeStoreItem(validationContext.ObjectType);
37+
var propertyStoreItem = typeStoreItem.GetPropertyStoreItem(validationContext.MemberName);
38+
return propertyStoreItem.ValidationAttributes;
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)