Unity IoC 和 MVC 模型绑定
我的控制器中可以有一个静态字段供我的模型绑定程序调用吗?
例如。
public class AuctionItemsController : Controller
{
private IRepository<IAuctionItem> GenericAuctionItemRepository;
private IAuctionItemRepository AuctionItemRepository;
public AuctionItemsController(IRepository<IAuctionItem> genericAuctionItemRepository, IAuctionItemRepository auctionItemRepository) {
GenericAuctionItemRepository = genericAuctionItemRepository;
AuctionItemRepository = auctionItemRepository;
StaticGenericAuctionItemRepository = genericAuctionItemRepository;
}
internal static IRepository<IAuctionItem> StaticGenericAuctionItemRepository;
这是
public class AuctionItemModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
if (AuctionItemsController.StaticGenericAuctionItemRepository != null) {
AuctionLogger.LogException(new Exception("controller is null"));
}
NameValueCollection form = controllerContext.HttpContext.Request.Form;
var item = AuctionItemsController.StaticGenericAuctionItemRepository.GetSingle(Convert.ToInt32(controllerContext.RouteData.Values["id"]));
item.Description = form["title"];
item.Price = int.Parse(form["price"]);
item.Title = form["title"];
item.CreatedDate = DateTime.Now;
item.AuctionId = 1;
//TODO: Stop hardcoding this
item.UserId = 1;
return item;
}}
我使用 Unity 作为 IoC 的模型绑定程序,我发现在 IoC 容器中注册我的模型绑定程序很奇怪。
我还应该考虑其他好的设计吗?
Is it ok to have a static field in my controller for my modelbinder to call ?
Eg.
public class AuctionItemsController : Controller
{
private IRepository<IAuctionItem> GenericAuctionItemRepository;
private IAuctionItemRepository AuctionItemRepository;
public AuctionItemsController(IRepository<IAuctionItem> genericAuctionItemRepository, IAuctionItemRepository auctionItemRepository) {
GenericAuctionItemRepository = genericAuctionItemRepository;
AuctionItemRepository = auctionItemRepository;
StaticGenericAuctionItemRepository = genericAuctionItemRepository;
}
internal static IRepository<IAuctionItem> StaticGenericAuctionItemRepository;
here is the modelbinder
public class AuctionItemModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
if (AuctionItemsController.StaticGenericAuctionItemRepository != null) {
AuctionLogger.LogException(new Exception("controller is null"));
}
NameValueCollection form = controllerContext.HttpContext.Request.Form;
var item = AuctionItemsController.StaticGenericAuctionItemRepository.GetSingle(Convert.ToInt32(controllerContext.RouteData.Values["id"]));
item.Description = form["title"];
item.Price = int.Parse(form["price"]);
item.Title = form["title"];
item.CreatedDate = DateTime.Now;
item.AuctionId = 1;
//TODO: Stop hardcoding this
item.UserId = 1;
return item;
}}
i am using Unity as IoC and I find it weird to register my modelbinder in the IoC container.
Any other good design considerations I shold do ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,我不认为这是一个好的做法。一般来说,API 设计(尤其是 DI)的美妙之处在于,一旦某些东西开始看起来很奇怪,它就应该触发心理警报。
static
关键字对我有这样的影响。一旦开始使用静态属性,就没有理由从控制器获取存储库 - 您也可以直接从容器获取它,这意味着 服务定位器反模式。就像现在一样,您将 ModelBinder 与特定的控制器紧密耦合,尽管您似乎没有理由这样做。
从技术上讲,您可以做已经做的事情,但要考虑它是否是正确的位置:既然您已经从存储库中获得了项目,为什么不立即再次保存它呢?这在技术上也是可行的,但严重违反了单一责任原则。
考虑一下 ModelBinder 的预期职责:它将 HTTP/HTML 上下文信息(以纯文本形式给出)转换为强类型对象。就是这样。如果你试图让它做更多事情,你就违反了建议零售价。
基于 HTML 表单/查询字符串值的脱水最好留给控制器本身。一旦控制器有了适当的领域对象,它就可以将其交给领域模型。这应该是财务主任的唯一责任。在大多数情况下,您根本不需要 ModelBinder。
No, I wouldn't consider this good practice. The beauty about API design in general, and DI in particular, is that as soon as something starts looking weird, it should trigger an mental alert. The
static
keyword has that effect on me.Once you start using static properties, there's no reason to get your repository from the Controlller - you might just as well get it directly from the container, and that would imply the Service Locator anti-pattern. As it is now, you tightly couple your ModelBinder to a specific Controller, although there seems to be no reason why you would want to do that.
Technically, you can do what you already do, but consider whether it's the correct place: now that you have your item from the repository, why not save it again immediately? That's also technically possible, but a big violation of the Single Responsibility Principle.
Think about the intended responsibility of a ModelBinder: it is to translate HTTP/HTML contextual information (given in plain text) into a strongly typed object. That's it. If you try to make it do more, you are breaking the SRP.
Dehydration based on HTML Form/querystring values is better left to the Controller itself. Once the Controller has a proper Domain Object, it can hand it off to the Domain Model. That should be the single responsibility of the Controller. In most cases you don't need a ModelBinder at all.