- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这确实是一个通用的(也可能是一个更主观的)问题。我在一些类中使用接口(interface)来定义验证对象状态的标准方法。当我这样做的时候,我开始挠头了……最好是1.) 允许构造函数(或初始化方法)自动过滤掉错误信息或...2.) 允许客户端实例化对象并让客户端在继续之前也调用接口(interface)的 IsValid 属性或 Validate() 方法?
基本上,一种方法是无声的,但可能会产生误导,因为客户可能不知道某些信息由于不符合验证标准而被过滤掉了。另一种方法会更直接,但还会增加一两步?这里有什么典型的?
好的,经过漫长的一天努力跟上其他一些事情,我终于想出了一个例子。请为我代劳,因为它并不理想,也绝不是什么美妙的东西,但希望它能很好地发挥作用,让人们明白这一点。我目前的项目太复杂了,无法为此做一些简单的事情,所以我编了一些东西……相信我……完全编好了。
好了,例子中的对象是这样的:
客户端:代表客户端代码(控制台应用顺便说一下)
IValidationInfo:这是我在当前项目中使用的实际界面。它允许我为不一定供客户端使用的“后端”对象创建验证框架,因为业务逻辑可能足够复杂。这也让我能够根据业务逻辑的需要分离验证代码和调用。
OrderManager:这是一个客户端代码可以用来管理订单的对象。可以说这是对客户友好的。
OrderSpecification:这是客户端代码可用于请求订单的对象。但是,如果业务逻辑无法解决,则可以引发异常(或者如果有必要,不添加订单并忽略异常......)在我的真实示例中,我实际上有一个不那么黑的对象 -白色的是这个栅栏的哪一侧......因此当我意识到我可以将验证请求(调用 IsValid 或 Validate())推送到 cilent 时,我最初的问题。
CustomerDescription:代表我分类的客户(假装是从数据库中读取的。
产品:表示也被分类的特定产品。
OrderDescription:代表官方订单请求。业务规则是客户不能订购任何他们未分类的东西(我知道..这不是很现实,但它给了我一些工作...)
好的...我刚刚意识到我无法在此处附加文件,所以这是代码。我为它的冗长外观道歉。这是我使用验证接口(interface)创建对客户友好的前端和业务逻辑后端所能做的最好的事情:
公共(public)类客户端 { static OrderManager orderMgr = new OrderManager();
static void Main(string[] args)
{
//Request a new order
//Note: Only the OrderManager and OrderSpecification are used by the Client as to keep the
// Client from having to know and understand the framework beyond that point.
OrderSpecification orderSpec = new OrderSpecification("Customer1", new Product(IndustryCategory.FoodServices, "Vending Items"));
orderMgr.SubmitOrderRequest(orderSpec);
Console.WriteLine("The OrderManager has {0} items for {1} customers.", orderMgr.ProductCount, orderMgr.CustomerCount);
//Now add a second item proving that the business logic to add for an existing customer works
Console.WriteLine("Adding another valid item for the same customer.");
orderSpec = new OrderSpecification("Customer1", new Product(IndustryCategory.FoodServices, "Sodas"));
orderMgr.SubmitOrderRequest(orderSpec);
Console.WriteLine("The OrderManager now has {0} items for {1} customers.", orderMgr.ProductCount, orderMgr.CustomerCount);
Console.WriteLine("Adding a new valid order for a new customer.");
orderSpec = new OrderSpecification("Customer2", new Product(IndustryCategory.Residential, "Magazines"));
orderMgr.SubmitOrderRequest(orderSpec);
Console.WriteLine("The OrderManager now has {0} items for {1} customers.", orderMgr.ProductCount, orderMgr.CustomerCount);
Console.WriteLine("Adding a invalid one will not work because the customer is not set up to receive these kinds of items. Should get an exception with message...");
try
{
orderSpec = new OrderSpecification("Customer3", new Product(IndustryCategory.Residential, "Magazines"));
orderMgr.SubmitOrderRequest(orderSpec);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
}
public interface IValidationInfo
{
string[] ValidationItems { get; }
bool IsValid { get; }
void Validate();
List<string> GetValidationErrors();
string GetValidationError(string itemName);
}
public class OrderManager
{
private List<OrderDescription> _orders = new List<OrderDescription>();
public List<OrderDescription> Orders
{
get { return new List<OrderDescription>(_orders); }
private set { _orders = value; }
}
public int ProductCount
{
get
{
int itemCount = 0;
this.Orders.ForEach(o => itemCount += o.Products.Count);
return itemCount;
}
}
public int CustomerCount
{
get
{
//since there's only one customer per order, just return the number of orders
return this.Orders.Count;
}
}
public void SubmitOrderRequest(OrderSpecification orderSpec)
{
if (orderSpec.IsValid)
{
List<OrderDescription> orders = this.Orders;
//Since the particular customer may already have an order, we might as well add to an existing
OrderDescription existingOrder = orders.FirstOrDefault(o => string.Compare(orderSpec.Order.Customer.Name, o.Customer.Name, true) == 0) as OrderDescription;
if (existingOrder != null)
{
List<Product> existingProducts = orderSpec.Order.Products;
orderSpec.Order.Products.ForEach(p => existingOrder.AddProduct(p));
}
else
{
orders.Add(orderSpec.Order);
}
this.Orders = orders;
}
else
orderSpec.Validate(); //Let the OrderSpecification pass the business logic validation down the chain
}
}
public enum IndustryCategory
{
Residential,
Textile,
FoodServices,
Something
}
public class OrderSpecification : IValidationInfo
{
public OrderDescription Order { get; private set; }
public OrderSpecification(string customerName, Product product)
{
//Should use a method in the class to search and retrieve Customer... pretending here
CustomerDescription customer = null;
switch (customerName)
{
case "Customer1":
customer = new CustomerDescription() { Name = customerName, Category = IndustryCategory.FoodServices };
break;
case "Customer2":
customer = new CustomerDescription() { Name = customerName, Category = IndustryCategory.Residential };
break;
case "Customer3":
customer = new CustomerDescription() { Name = customerName, Category = IndustryCategory.Textile };
break;
}
//Create an OrderDescription to potentially represent the order... valid or not since this is
//a specification being used to request the order
this.Order = new OrderDescription(new List<Product>() { product }, customer);
}
#region IValidationInfo Members
private readonly string[] _validationItems =
{
"OrderDescription"
};
public string[] ValidationItems
{
get { return _validationItems; }
}
public bool IsValid
{
get
{
List<string> validationErrors = GetValidationErrors();
if (validationErrors != null && validationErrors.Count > 0)
return false;
else
return true;
}
}
public void Validate()
{
List<string> errorMessages = GetValidationErrors();
if (errorMessages != null && errorMessages.Count > 0)
{
StringBuilder errorMessageReported = new StringBuilder();
errorMessages.ForEach(em => errorMessageReported.AppendLine(em));
throw new Exception(errorMessageReported.ToString());
}
}
public List<string> GetValidationErrors()
{
List<string> errorMessages = new List<string>();
foreach (string item in this.ValidationItems)
{
string errorMessage = GetValidationError(item);
if (!string.IsNullOrEmpty(errorMessage))
errorMessages.Add(errorMessage);
}
return errorMessages;
}
public string GetValidationError(string itemName)
{
switch (itemName)
{
case "OrderDescription":
return ValidateOrderDescription();
default:
return "Invalid item name.";
}
}
#endregion
private string ValidateOrderDescription()
{
string errorMessage = string.Empty;
if (this.Order == null)
errorMessage = "Order was not instantiated.";
else
{
if (!this.Order.IsValid)
{
List<string> orderErrors = this.Order.GetValidationErrors();
orderErrors.ForEach(ce => errorMessage += "\n" + ce);
}
}
return errorMessage;
}
}
public class CustomerDescription : IValidationInfo
{
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public int ZipCode { get; set; }
public IndustryCategory Category { get; set; }
#region IValidationInfo Members
private readonly string[] _validationItems =
{
"Name",
"Street",
"City",
"State",
"ZipCode",
"Category"
};
public string[] ValidationItems
{
get { return _validationItems; }
}
public bool IsValid
{
get
{
List<string> validationErrors = GetValidationErrors();
if (validationErrors != null && validationErrors.Count > 0)
return false;
else
return true;
}
}
public void Validate()
{
List<string> errorMessages = GetValidationErrors();
if (errorMessages != null && errorMessages.Count > 0)
{
StringBuilder errorMessageReported = new StringBuilder();
errorMessages.ForEach(em => errorMessageReported.AppendLine(em));
throw new Exception(errorMessageReported.ToString());
}
}
public List<string> GetValidationErrors()
{
List<string> errorMessages = new List<string>();
foreach (string item in this.ValidationItems)
{
string errorMessage = GetValidationError(item);
if (!string.IsNullOrEmpty(errorMessage))
errorMessages.Add(errorMessage);
}
return errorMessages;
}
public string GetValidationError(string itemName)
{
//Validation methods should be called here... pretending nothings wrong for sake of discussion & simplicity
switch (itemName)
{
case "Name":
return string.Empty;
case "Street":
return string.Empty;
case "City":
return string.Empty;
case "State":
return string.Empty;
case "ZipCode":
return string.Empty;
case "Category":
return string.Empty;
default:
return "Invalid item name.";
}
}
#endregion
}
public class Product
{
public IndustryCategory Category { get; private set; }
public string Description { get; private set; }
public Product(IndustryCategory category, string description)
{
this.Category = category;
this.Description = description;
}
}
public class OrderDescription : IValidationInfo
{
public CustomerDescription Customer { get; private set; }
private List<Product> _products = new List<Product>();
public List<Product> Products
{
get { return new List<Product>(_products); }
private set { _products = value; }
}
public OrderDescription(List<Product> products, CustomerDescription customer)
{
this.Products = products;
this.Customer = customer;
}
public void PlaceOrder()
{
//If order valid, place
if (this.IsValid)
{
//Do stuff to place order
}
else
Validate(); //cause the exceptions to be raised with the validate because business rules were broken
}
public void AddProduct(Product product)
{
List<Product> productsToEvaluate = this.Products;
//some special read, validation, quantity check, pre-existing, etc here
// doing other stuff...
productsToEvaluate.Add(product);
this.Products = productsToEvaluate;
}
#region IValidationInfo Members
private readonly string[] _validationItems =
{
"Customer",
"Products"
};
public string[] ValidationItems
{
get { return _validationItems; }
}
public bool IsValid
{
get
{
List<string> validationErrors = GetValidationErrors();
if (validationErrors != null && validationErrors.Count > 0)
return false;
else
return true;
}
}
public void Validate()
{
List<string> errorMessages = GetValidationErrors();
if (errorMessages != null && errorMessages.Count > 0)
{
StringBuilder errorMessageReported = new StringBuilder();
errorMessages.ForEach(em => errorMessageReported.AppendLine(em));
throw new Exception(errorMessageReported.ToString());
}
}
public List<string> GetValidationErrors()
{
List<string> errorMessages = new List<string>();
foreach (string item in this.ValidationItems)
{
string errorMessage = GetValidationError(item);
if (!string.IsNullOrEmpty(errorMessage))
errorMessages.Add(errorMessage);
}
return errorMessages;
}
public string GetValidationError(string itemName)
{
switch (itemName)
{
case "Customer":
return ValidateCustomer();
case "Products":
return ValidateProducts();
default:
return "Invalid item name.";
}
}
#endregion
#region Validation Methods
private string ValidateCustomer()
{
string errorMessage = string.Empty;
if (this.Customer == null)
errorMessage = "CustomerDescription is missing a valid value.";
else
{
if (!this.Customer.IsValid)
{
List<string> customerErrors = this.Customer.GetValidationErrors();
customerErrors.ForEach(ce => errorMessage += "\n" + ce);
}
}
return errorMessage;
}
private string ValidateProducts()
{
string errorMessage = string.Empty;
if (this.Products == null || this.Products.Count <= 0)
errorMessage = "Invalid Order. Missing Products.";
else
{
foreach (Product product in this.Products)
{
if (product.Category != Customer.Category)
{
errorMessage += string.Format("\nThe Product, {0}, category does not match the required Customer category for {1}", product.Description, Customer.Name);
}
}
}
return errorMessage;
}
#endregion
}
最佳答案
如果信息有效,您有什么理由不希望构造函数大声抛出异常?根据我的经验,最好避免创建处于无效状态的对象。
关于c# - 验证的最佳位置在哪里...构造函数或留给客户调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15032808/
我正在尝试获取从过去的 startposition/location 到当前移动的 currentposition/location 的距离(以米为单位)。 我确实有工作正常的currentposit
所以我有一堆绝对覆盖的 div。用户通过在叠加层上拖动来创建方形 div。如果您要创建一个 div,然后放大和缩小,div 会保持在同一位置,因为它对叠加层是绝对的,如前所述。 然而问题就出在这里。您
我想找到 View 在显示屏幕上的位置。 为此,我使用了 view.getLeft() 、view.getBottom() 、view.getRight() 等方法> , view.getTop()。
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
所以我有一个名为 MARKS 的表,我有这些列 STUDENT_ID, CLASSFORM_NAME, ACADEMIC_YEAR, TERM, SUBJECT_NAME, TOTAL_MARKS
我有一个问题我无法理解,请帮助: 我开发了带有图像的 html 页面,并使用 jQuery UI 帮助使它们可拖动,我将这些图像位置设置为相对位置并给出了左侧和顶部像素,这是页面的链接 http://
我正在尝试创建一个 CSS 动画,它在 sprite 表中循环播放 16 个图像,给人一种幽灵“漂浮”的错觉。动画通过在 background-position 位置之间移动以显示不同状态的幽灵来实现
我正在创建这个网站的 WebView https://nearxt.com/打开时询问位置但是当我使用此链接在 flutter 中创建 webview 时那么它就无法定位我还在应用程序中定义了位置,但
我正在以编程方式创建一个需要跨越 2 个屏幕的窗口。正在创建的窗口的大小是正确的,但窗口大约从第一个屏幕的一半开始。我可以将它拖回第一个屏幕的开头,NSWindow 非常适合。 我只需要知道在窗口的起
位置“/”的匹配叶路由没有元素。这意味着默认情况下它将呈现一个空值,从而导致一个“空”页面 //App.js File import { BrowserRouter as Router, Routes
我有一个运行 Ubuntu 和 Apache 的 VPS 例如,假设地址是:5.5.5.5 在 VPS 上,我有一个名为 eggdrop 的用户(除了我的 root 用户)。 用户 eggdrop 有
我有一个 JLabel与 ImageIcon ,我使用 setIcon() JLabel中的函数. ImageIcon然后上来,坐在我的JLabel 的文字左侧.是否有可能拥有 ImageIcon在文
我的图中有节点,它们的 xlabels 位于它们的左上方。我怎样才能改变这个位置?我希望 xlabels 正好位于节点本身的旁边。 最佳答案 xlp是你想要的属性,但它没有做任何事情。 你不能改变位置
我对基本的 VIM 功能有疑问:(我尝试谷歌搜索但找不到答案) 如何列出所有自定义功能。(我做了 :function 并且不能找到我的自定义函数) 如何获得自定义函数列表中的函数(或它们的存储位置)。
我是 PHP 的新手,虽然我一直在搜索,但我不知道该怎么做。 我知道可以使用 Location("some page") 进行重定向。我还读到,只要没有向用户显示任何内容,它就可以工作。 我想做的是:
如果在 jgrowl.css 中位置更改为“center”,我如何将其覆盖为默认值,即“top-right” $.jGrowl(data, { header: 'data', an
我需要根据用户是否滑动屏幕顶部、屏幕中间或屏幕底部来触发不同的事件。我正在尝试找出最好/最简单的方法来做到这一点,因为我很确定没有办法从 UISwipeGestureRecognizer 获取位置。
我需要枚举用delphi编写的外部应用程序中使用的类 ,因此我需要访问VMT表以获取该信息,但是我找不到任何有关如何在exe(由delphi生成)文件中找到VMT(虚拟方法表)的位置(地址)的文档。
在 D2010 (unicode) 中是否有像 Pos 这样不区分大小写的类似函数? 我知道我可以使用 Pos(AnsiUpperCase(FindString), AnsiUpperCase(Sou
我正在尝试为我的reveal.js 演示文稿制作一个标题,该标题会粘贴在屏幕顶部。标题中的内容在每张幻灯片的基础上都是动态的,因此我必须将标记放在 section 标记中。 显然,如果标记在 sect
我是一名优秀的程序员,十分优秀!