13 private static readonly Dictionary<string, LinkedList<PhoneNumberScheme>> schemesByCode = [];
14 private static LinkedList<PhoneNumberScheme>? defaultSchemes;
16 private static void LazyLoad()
18 if (defaultSchemes is not
null || schemesByCode.Count > 0)
26 XmlDocument Doc =
new();
29 XmlNodeList? ChildNodes = Doc.DocumentElement?.ChildNodes;
31 if (ChildNodes is
null)
34 foreach (XmlNode N
in ChildNodes)
36 if (N is XmlElement E && E.LocalName ==
"Entry")
39 string DisplayString =
XML.
Attribute(E,
"displayString");
47 foreach (XmlNode N2
in E.ChildNodes)
49 if (N2 is XmlElement E2)
74 if (Pattern is
null ||
string.IsNullOrWhiteSpace(
Variable) ||
string.IsNullOrWhiteSpace(DisplayString))
81 defaultSchemes ??=
new LinkedList<PhoneNumberScheme>();
82 defaultSchemes.AddLast(Scheme);
86 if (!schemesByCode.TryGetValue(Country, out LinkedList<PhoneNumberScheme>? List))
88 List =
new LinkedList<PhoneNumberScheme>();
89 schemesByCode[Country] = List;
111 async Task<PhoneNumberInformation?> TrySchemes(LinkedList<PhoneNumberScheme>? schemes)
116 foreach (var scheme
in schemes)
118 var info = await scheme.Validate(rawNumber);
119 if (info.IsValid.HasValue)
121 info.DisplayString = scheme.DisplayString;
129 if (!
string.IsNullOrWhiteSpace(countryCode) &&
130 schemesByCode.TryGetValue(countryCode!, out var byCountry))
132 var hit = await TrySchemes(byCountry);
139 var hit = await TrySchemes(defaultSchemes);
145 if (!
string.IsNullOrWhiteSpace(countryCode) && schemesByCode.ContainsKey(countryCode!))
149 Original = rawNumber,
150 DisplayString =
string.Empty,
157 Original = rawNumber,
158 DisplayString =
string.Empty,
169 if (!
string.IsNullOrWhiteSpace(countryCode) &&
170 schemesByCode.TryGetValue(countryCode, out var list))
172 return list?.First?.Value?.DisplayString;
178 #region Support types (mirrors your PersonalNumberScheme/NumberInformation style)
182 public string DisplayString {
get; }
189 this.Variable = variable;
190 this.DisplayString = displayString;
191 this.pattern = pattern;
193 this.normalize = normalize;
196 public async Task<PhoneNumberInformation> Validate(
string input)
205 var patternResult = await this.pattern.EvaluateAsync(v);
208 if (patternResult is not
bool matched || !matched)
212 if (this.check is not
null)
214 var checkResult = await this.check.EvaluateAsync(v);
215 if (checkResult is not
bool ok || !ok)
220 string normalized = input;
221 if (this.normalize is not
null)
223 var norm = await this.normalize.EvaluateAsync(v);
224 if (norm is
string s)
231 Normalized = normalized,
245 public string? Original {
get;
set; }
246 public string? Normalized {
get;
set; }
247 public string? DisplayString {
get;
set; }
Phone Number Schemes with country-specific pattern/check/normalize, E.164-first.
static ? string DisplayStringForCountry(string countryCode)
Gets a human-friendly example format for a country (first scheme display string).
static async Task< PhoneNumberInformation > ValidateAndNormalize(string? countryCode, string rawNumber)
Validates and normalizes a phone number according to configured schemes.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Static class managing loading of resources stored as embedded resources or in content files.
static byte[] LoadResource(string ResourceName)
Loads a resource from an embedded resource.
Class managing a script expression.
Contains information about a variable.