我已经构建了一个如下所示的MVC应用程序:
MVC Application - Application Layer - Business Layer - Repository - Data
我已经阅读了many个应用程序的代码,并发现没有人似乎以类似于传递数据的方式传递异常。
换句话说,数据通过接口引用并在不同的上下文中重用。如果数据层中发生异常,它将如何发送到GUI或相关层?应该使用接口吗?在this应用程序中处理异常的构造是什么?
答案 0 :(得分:5)
我没有读过你链接的doco但是我有一个简单的例子,我提出异常以回应不满足不变量。假设我正在创建一个实例,由于某种原因它是“无效的”,假设用户输入不好。而不是让我的实体处于无效状态(在DDD中是禁止的)并让系统“验证”它,它会在创建时抛出异常。相关的“验证消息”(对于用户)是从不满足的同一规范实例中提取的,我的派生异常包含UI所需的值。
InvariantException
的示例:
public class InvariantException : MyAppException
{
public object FailingObject = null;
public ModelStateDictionary ModelState = new ModelStateDictionary();
public InvariantException() { }
public InvariantException(object failingObject, ModelStateDictionary messages)
{
this.FailingObject = failingObject;
this.ModelState = messages;
}
public InvariantException(object failingObject, ModelStateDictionary messages,
Exception innerException)
: base("refer to ModelState", innerException)
{
this.FailingObject = failingObject;
this.ModelState = messages;
}
}
为用户/用户界面返回相关“验证消息”的规范示例:
public class PostFieldLengthSpecification : ISpecification<Post>
{
private const string TITLE_LENGTH_RANGE = "5-100";
private const string BODY_LENGTH_RANGE = "20-10000";
public bool IsSatisfiedBy(Post post)
{
return this.GetErrors(post).IsValid;
}
public ModelStateDictionary GetErrors(Post post)
{
ModelStateDictionary modelState = new ModelStateDictionary();
if (!post.Title.Trim().Length.Within(TITLE_LENGTH_RANGE))
modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.Title),
"Please make sure the title is between {0} characters in length".With(TITLE_LENGTH_RANGE));
if (!post.BodyMarkup.Trim().Length.Within(BODY_LENGTH_RANGE))
modelState.AddModelError(StongTypeHelpers.GetPropertyName((Post p) => p.BodyMarkup),
"Please make sure the post is between {0} characters in length".With(BODY_LENGTH_RANGE));
return modelState;
}
}
工厂如何永远不会创建无效实例的示例,而是抛出异常并为UI存放消息:
public static Post GetNewPost(string title, string bodyMarkup, DateTime posted)
{
var post = new Post(0, title, bodyMarkup, posted, new List<Comment>());
var fieldLengthSpec = new PostFieldLengthSpecification();
if (fieldLengthSpec.IsSatisfiedBy(post))
return post;
else
throw new InvariantException(post, fieldLengthSpec.GetErrors(post));
}
最后,一个自定义模型绑定器的示例,用于捕获所述异常并将“无效对象”传递回具有错误消息的操作:
public class PostModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(Post))
{
try
{
// Create Post
return base.BindModel(controllerContext, bindingContext);
}
catch (InvariantException ie)
{
// If invalid, add errors from factory to ModelState
bindingContext.ModelState.AddNewErrors(ie.ModelState);
bindingContext.ModelState.AddValuesFor<Post>(bindingContext.ValueProvider);
return ie.FailingObject;
}
}
希望这有帮助。