验证对象的基于外部因素(即。数据储存的独特性)
-
19-09-2019 - |
题
描述
我的解决方案具有这些项目:
- DAL =修改实体框架
- 也可与检 =数据传送对象,是能够确认自己
- BL =业务层服务
- 网 =介绍Asp.net 软应用程序
DAL、BL和网络都参照也可与检这是伟大的。
该过程通常执行这一方式:
- 一个网请求是由于该网
- 网络获取的交互发表
- 交互得到自动的经验证通过自定义ActionFilter
- 验证错误的自动收集
- (验证的"确定")的网调入BL提供交互
- BL调入达尔通过使用交互(可以通过他们通过,或只是使用他们)
也可与检验证的问题,然后...
我的交互都能够确认自己根据自己的国家(产值)。但现在我提出了一个问题时,这个不是这种情况。我需要他们来验证使用BL(和因此DAL).
我的现实生活中的例子:用户注册和网络得到一个用户也可与检得到验证。该问题的一部分是 username
验证。它的独特性,应该核对数据存储。
我应该怎么做到这个吗?
有其他信息,所有的交互实现一个接口(ie。 User
也可与检实现了 IUser
)对于IoC目和文字.两者都部分 也可与检项目.
不可能试图
- 我不能参BL在也可与检因为我会得到圆参考。
Compilation error
- 我不能创建一个额外也可与检.Val项目,该项目将参考部分也可与检课程和实施自己的验证有(他们会参考BL+也可与检).
Partial classes can't span assemblies.
可能会尝试
- 创建一个特殊的
ActionFilter
这将验证对象的外部条件。这一会内创建的 网项目 因此,看到的也可与检和BL,将使用在这里。 - 把交互BL和保留也可与检接口,作为实际的交互参考的其他项目和重构所有代码使用的接口,而不是具体的课程。
- 不要处理依赖外部验证和让外部的依赖扔一个例外可能是 最糟糕的 解决这个问题
你有什么建议吗?
解决方案 4
得到的解决方案
我最终使用控制器行动过滤器,是能够确认对象外部因素,不能从所获得的对象本身。
我创造的过滤器的名称操作参数的检查和验证程序的类型,这将验证的特定参数。当然,这种验证程序已经实施的某些接口,使它所有的可重复使用。
[ValidateExternalFactors("user", typeof(UserExternalValidator))]
public ActionResult Create(User user)
验证程序需要实现这个简单的接口
public interface IExternalValidator<T>
{
bool IsValid(T instance);
}
这是一个简单和有效的解决看似复杂的问题。
其他提示
我建议一个实验,我只是试的最后一个星期左右。
基于上 这个灵感 我创造的交互验证一点不同的 DataAnnotations
办法。样品也可与检:
public class Contact : DomainBase, IModelObject
{
public int ID { get; set; }
public string Name { get; set; }
public LazyList<ContactDetail> Details { get; set; }
public DateTime Updated { get; set; }
protected override void ConfigureRules()
{
base.AddRule(new ValidationRule()
{
Properties = new string[] { "name" },
Description = "A Name is required but must not exceed 300 characters in length and some special characters are not allowed",
validator = () => this.Name.IsRequired300LenNoSpecial()
});
base.AddRule(new ValidationRule()
{
Properties = new string[] { "updated" },
Description = "required",
validator = () => this.Updated.IsRequired()
});
}
}
这可能看起来更多的工作比 DataAnnotations
和幸,这是因为它是的,但这不是巨大的。我想这更像样在类(我有一些很丑也可与检类现在有了 DataAnnotations
属性-你甚至都不能看到的性质的任何更多)。和力量的匿名代表在这个应用程序是几乎书的价值(因此我发现).
基类:
public partial class DomainBase : IDataErrorInfo
{
private IList<ValidationRule> _rules = new List<ValidationRule>();
public DomainBase()
{
// populate the _rules collection
this.ConfigureRules();
}
protected virtual void ConfigureRules()
{
// no rules if not overridden
}
protected void AddRule(ValidationRule rule)
{
this._rules.Add(rule);
}
#region IDataErrorInfo Members
public string Error
{
get { return String.Empty; } // Validation should call the indexer so return "" here
} // ..we dont need to support this property.
public string this[string columnName]
{
get
{
// get all the rules that apply to the property being validated
var rulesThatApply = this._rules
.Where(r => r.Properties.Contains(columnName));
// get a list of error messages from the rules
StringBuilder errorMessages = new StringBuilder();
foreach (ValidationRule rule in rulesThatApply)
if (!rule.validator.Invoke()) // if validator returns false then the rule is broken
if (errorMessages.ToString() == String.Empty)
errorMessages.Append(rule.Description);
else
errorMessages.AppendFormat("\r\n{0}", rule.Description);
return errorMessages.ToString();
}
}
#endregion
}
ValidationRule
和我的验证功能:
public class ValidationRule
{
public string[] Properties { get; set; }
public string Description { get; set; }
public Func<bool> validator { get; set; }
}
/// <summary>
/// These extention methods return true if the validation condition is met.
/// </summary>
public static class ValidationFunctions
{
#region IsRequired
public static bool IsRequired(this String str)
{
return !str.IsNullOrTrimEmpty();
}
public static bool IsRequired(this int num)
{
return num != 0;
}
public static bool IsRequired(this long num)
{
return num != 0;
}
public static bool IsRequired(this double num)
{
return num != 0;
}
public static bool IsRequired(this Decimal num)
{
return num != 0;
}
public static bool IsRequired(this DateTime date)
{
return date != DateTime.MinValue;
}
#endregion
#region String Lengths
public static bool IsLengthLessThanOrEqual(this String str, int length)
{
return str.Length <= length;
}
public static bool IsRequiredWithLengthLessThanOrEqual(this String str, int length)
{
return !str.IsNullOrTrimEmpty() && (str.Length <= length);
}
public static bool IsRequired300LenNoSpecial(this String str)
{
return !str.IsNullOrTrimEmpty() &&
str.RegexMatch(@"^[- \r\n\\\.!:*,@$%&""?\(\)\w']{1,300}$",
RegexOptions.Multiline) == str;
}
#endregion
}
如果我的代码看起来很凌乱的好,这是因为我只在这方面的工作验证办法的最后几天。我需要这个想法,以满足一些要求:
- 我需要支持
IDataErrorInfo
接口,所以我的软层验证自动 - 我需要能够支持复杂的验证方案(整点你的问题我猜):我希望能够证实,对多个性质上相同的对象(即。起始日期和FinishDate);性从不同/多重/相关对象喜欢我会有一个目的曲线图;甚至是其他的事情我还没想过呢。
- 我需要支持这一想法的错误适用于多于一个酒店
- 作为我的一部分和DDD的旅程我想我域对象来描述我域'比我的服务层方法,所以把这些复杂的条件下,在该模型的对象(未交互)似乎实现了这个
这种方法,我认为将得到我我想要什么,也许你。
我想象一下如果你跳上我在这,我们会很漂亮的'自己',但它可能是值得的。我读到的 新验证功能在软2 但它仍然不能满足上述愿望清单没有定义的修改。
希望这会有所帮助。
S#arp构具有一个[DomainSignature]方法的标识,使用与该类一级的验证程序[HasUniqueDomainSignature]将做的工作。看样的代码如下:
[HasUniqueDomainSignature]
public class User : Entity
{
public User()
{
}
public User(string login, string email) : this()
{
Login = login;
Email = email;
}
[DomainSignature]
[NotNullNotEmpty]
public virtual string Login { get; set; }
[DomainSignature]
public virtual string Email { get; set; }
}
我不得不这完全相同的问题和后试图找到一个工作周围的几天和几天和几天,我结束了,合并我也可与检DAL和BL入一个图书馆。我继续我的演讲层分开。不知道,如果这是一个选择或没有。对我来说,我想我的机会不断变化的数据储存是很轻微的,因此单独的级别并不是真正需要的。
我也已经实施的微软应用程序的验证框我所有的也可与检验证。他们有一个"自我验证"的方法,可以执行复杂的验证。