我可以完成这项工作的唯一方法是获取 .Net 的源代码并自己调整它以允许电子邮件属性的可为空值。
代码可以在这里找到:https ://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/EmailAddressAttribute.cs
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class NullableEmailAddressAttribute : DataTypeAttribute
{
// This attribute provides server-side email validation equivalent to jquery validate,
// and therefore shares the same regular expression. See unit tests for examples.
private static Regex _regex = CreateRegEx();
public NullableEmailAddressAttribute()
: base(DataType.EmailAddress)
{
// DevDiv 468241: set DefaultErrorMessage not ErrorMessage, allowing user to set
// ErrorMessageResourceType and ErrorMessageResourceName to use localized messages.
// DefaultErrorMessage = DataAnnotationsResources.EmailAddressAttribute_Invalid;
}
public override bool IsValid(object value)
{
if (value == null)
return true;
string valueAsString = value as string;
if (string.IsNullOrEmpty(valueAsString))
return true;
// Use RegEx implementation if it has been created, otherwise use a non RegEx version.
if (_regex != null)
{
return valueAsString != null && _regex.Match(valueAsString).Length > 0;
}
else
{
int atCount = 0;
foreach (char c in valueAsString)
{
if (c == '@')
{
atCount++;
}
}
return (valueAsString != null
&& atCount == 1
&& valueAsString[0] != '@'
&& valueAsString[valueAsString.Length - 1] != '@');
}
}
private static Regex CreateRegEx()
{
// We only need to create the RegEx if this switch is enabled.
//if (AppSettings.DisableRegEx)
//{
// return null;
//}
const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";
const RegexOptions options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
// Set explicit regex match timeout, sufficient enough for email parsing
// Unless the global REGEX_DEFAULT_MATCH_TIMEOUT is already set
TimeSpan matchTimeout = TimeSpan.FromSeconds(2);
try
{
if (AppDomain.CurrentDomain.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") == null)
{
return new Regex(pattern, options, matchTimeout);
}
}
catch
{
// Fallback on error
}
// Legacy fallback (without explicit match timeout)
return new Regex(pattern, options);
}
}
用法是这样的:
[NullableEmailAddress]
public string DigitalInvoiceEmail { get; set; }