我试图在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's answer here中一样,但ASP.NET抛出了一个编译错误,Razor不知道如何处理属性名称,因为它没有定义。
有没有办法完成对这些特定于实现的属性的绑定,并且仍然受益于ASP.NET MVC提供的强类型?我是否在使用自定义绑定的正确轨道上,但只是拙劣的实现?提前感谢任何建议。
编辑:我将@Html.EditorFor(x => x.FooItem.ConcreteProperty)
替换为@Html.EditorFor(x => (x.FooItem as ConcreteFoo).ConcreteProperty)
,这会导致绑定成功。不过还有更好的办法吗?
答案 0 :(得分:2)
public abstract class BaseFoo
{
public virtual string FooText { get; set; }
}
public class ConcreteFoo : BaseFoo
{
public override string FooText { get; set; }
}
答案 1 :(得分:1)
您正在做的事情违反了面向对象编程的原则。你已经有了一个基类,并且你试图像派生类一样对待它,而这只是一个巨大的红旗。如果您需要派生类,那么您应该在模型中有一个派生类。
否则你唯一的选择是施放,这是一个巨大的代码气味,如果对象实际上不是你认为的衍生对象,则可能存在缺陷。
很可能,您真正的问题是您尝试使用某种域模型作为您的视图模型。您应该将视图模型自定义为该视图所需的模型。然后,您应该将您的域模型映射到您的视图模型,并执行此时所需的任何转换。