我试图在ASP.NET MVC视图的绑定模型中访问抽象对象的具体实现,但是我不知道如何绑定到该属性的属性,而该属性是其具体实现的一部分。
public abstract class BasePageVO
{
public string DisplayText { get; set; }
public BaseFoo FooItem { get; set; }
}
public class ConcretePageVO : BasePageVO
{
// some properties
// in a concrete page, the concrete implementation of BaseFoo is known at compile time.
}
public abstract class BaseFoo
{
public string FooText { get; set; }
}
public class ConcreteFoo : BaseFoo
{
public string ConcreteProperty { get; set; }
}
更重要的是,为什么我采用了这样一个异常的类结构,是因为共享的部分也需要了解FooItem,但只需要了解其抽象属性。下面是结构的简化轮廓:
DisplayFoo.cshtml:
@model ConcretePageVO
@using (Html.BeginForm("Submit", "Foo", FormMethod.Post)
{
@Html.Partial("DisplayFooShared", @Model)
@Html.EditorFor(x => x.FooItem.ConcreteProperty) @* This fails *@
}
DisplayFooShared.cshtml:
@model BasePageVO
<div>
@Html.DisplayFor(x => x.DisplayText)
@Html.EditorFor(x => x.FooItem.FooText)
@* More properties... *@
</div>
有没有一种方法可以向Razor指示BaseFoo对象属于预期的具体类型,并且仍然受益于我如何在共享的局部视图中执行模型绑定?我以为我为BaseFoo创建自己的自定义模型绑定是在正确的轨道上,就像Darin在这里给出的答案一样,但是ASP.NET引发了一个编译错误,Razor不知道如何处理属性名称,因为它不是。定义。
有没有一种方法可以完成对这些特定于实现的属性的绑定,并仍然受益于ASP.NET MVC提供的强大类型?我是否在使用自定义绑定的过程中走了一条正确的路,而仅仅破坏了实现?在此先感谢您的任何建议。
编辑:我替换@Html.EditorFor(x => x.FooItem.ConcreteProperty)
为@Html.EditorFor(x => (x.FooItem as ConcreteFoo).ConcreteProperty)
,这将导致绑定成功。不过,还有更好的方法吗?
您所做的违反了面向对象编程的原理。您有一个基类,并且试图将其像派生类一样对待,这只是一个巨大的危险信号。如果需要派生类,则模型中应该有一个派生类。
否则,您唯一的选择就是强制转换,这是一种巨大的代码味道,如果对象实际上不是您认为的实际派生对象,则可能存在缺陷。
您真正的问题很可能是您正在尝试使用某种域模型作为视图模型。您应该自定义视图模型,使其恰好是该视图所需的模型。然后,您应该将域模型映射到视图模型,然后进行必要的任何转换。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句