剃刀模型铸造

时间:2012-08-04 14:50:54

标签: asp.net-mvc-3 razor casting data-annotations system.reflection

如何将Model(接口类型)转换为实际类型?

您在下面看到的显然是简化版本,专注于手头的问题。所以问题是如何重新构建我的解决方案,但特别是如何在剃刀中将接口类型模型实例转换为实际的类类型。

查看型号:

public interface IData
{
  string Data { get; set; }
}
public class Child1 : IData
{
  [Display(Name = "Name1", Description = "Desc1", Prompt = "Prompt1")]
  public string Data { get; set; }
}
public class Child2 : IData
{
  [Display(Name = "Name2", Description = "Desc2", Prompt = "Prompt2")]
  public string Data { get; set; }
}
// It gets to Child10 and there is dynamic number of each of them in the main ViewModel

在视图中我需要显示数据注释,但MVC不会在面向对象的时候执行它。 如果我只是说

@model <path to>.IData
@Html.LabelFor(m => model.Data)
@Html.TextBoxFor(m => model.Data)
@Html.ValidationMessageFor(m => model.Data)

我得到了界面上定义的内容,而不是实际类中的内容。 愚蠢的解决方案是进行巨大的切换并将模型转换为它来自的实际类型:

@switch(Model.GetType().Name)
{
  case "Child1":
    var c1 = Model as Child1;
    @Html.LabelFor(m => c1.Data)
    @Html.TextBoxFor(m => c1.Data)
    @Html.ValidationMessageFor(m => c1.Data)
    break;
  // etc 
}

如果我有超过3个孩子的IBase(而且我这样做),开关变得无法管理,更不用说看起来很难看了。 而不是进行切换,我如何使用反射来获取Model的类型? 请注意,简单

@{
  var c1 = Model as Model.GetType();
  var c2 = (Model.GetType()) Model;
  var c3 = (Type.GetType(Model.GetType())) Model;
  var c4 = Model as Type.GetType(Model.GetType();
}

等会发出可怕的警告,当然也不会在剃须刀中运行。

我确信通过模型的反射可以获得,但无论我尝试过什么都行不通。 希望你们有一些新鲜的想法。

小更新

我无法将X为数字的Child组合成一个模型,因为事先不知道它们有多少,在主视图中可以添加/删除它们。我绘制的图片非常特定于此问题,视图/控制器/模型比您在此处看到的要复杂得多。

提前致谢。

1 个答案:

答案 0 :(得分:2)

关于您的示例的快速说明:您显示了IBase的界面,但您的类正在实现接口IData。

您的模型应该是您要使用的实际类型的对象(或者包含您要使用的类型的属性),而不是让您的模型成为接口。

例如,如果要在视图中显示有关这两个子项的数据,请按以下方式设置模型:

public class ChildModel {
  public Child1 { get; set; }
  public Child2 { get; set; }
}
public class Child1 : IData
{
  [Display(Name = "Name1", Description = "Desc1", Prompt = "Prompt1")]
  public string Data { get; set; }
}
public class Child2 : IData
{
  [Display(Name = "Name2", Description = "Desc2", Prompt = "Prompt2")]
  public string Data { get; set; }
}

如果您将ChildModel返回到视图中,那么您不需要在视图中进行任何投射(无论如何都应该避免)。