动态类型化的ViewPage(Dynamic typed ViewPage)

2019-06-26 17:14发布

这可能吗? 这里就是我想:

    public ActionResult Index()
    {
        dynamic p = new { Name = "Test", Phone = "111-2222" };
        return View(p);
    }

然后我认为从继承System.Web.Mvc.ViewPage<dynamic>并尝试打印出Model.Name。

我发现了一个错误:“<> f__AnonymousType1.Name”不可访问由于其保护级别

因此,基本上,是什么,我试图做是不可能的? 为什么或者为什么不?

更新:这是我的看法

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<asp:Content ...>
    <%=Model.Name%>
    <%=Model.Phone%>
</asp:Content>

该视图构造函数是内置的框架。

Answer 1:

匿名类型不能由方法返回; 它们仅在它们所定义的方法的范围内有效。

您应该使用您先前定义的模型类,并传递到您的视图。 有什么错传递一个没有定义的每个领域模型的类。

更新

我想我以前是错的。 这应该工作。 也许问题是在视图中。 你可以发布更多的代码? 特别是查看它的构造。

更新第二:

好吧,我错了关于通过一个匿名类型的另一种方法用作动态变量 - 是可以做到的。

但是,我也错了,我相信,你正在试图做的工作会是什么。 不幸的是你,也不会。 的问题是,使用的是ViewPage<TModel> ,它使用ViewDataDictionary<TModel>内部。 因为他们需要强大的类型,您将无法使用动态对象和他们在一起。 内部结构只是不使用动态内部,并指定动态作为类型失败。

需要怎么做才能是一个DynamicViewPage类和相应的DynamicViewDataDictionary类接受object ,并在内部存储它作为一个动态的。 然后,你可以使用匿名类型,并把它传递给你的意见。

这就是说,你不会得到任何东西。 你就可以指定你的意见,你所做的(即<%=Model.Name%> ),但你不会从强类型中受益。 就没有IntelliSense和就没有类型安全。 你会做的一样好使用非类型化ViewDataDictionary作为@Dennis帕尔默建议。

这是一个有趣的(而且,不幸的是我,吸收)的思想实验,但我认为,最终,它不会发生。 无论是声明的公共类型并将它传递给你的意见,或使用无类型的字典。



Answer 2:

是你希望得到什么好处从这里使用动态类型获得?

使用ViewData字典是将任意的对象/项目视图输出的一个非常简单的方法。

你不需要反射到你的视图中获得的属性名称。 只需使用ViewData.Keys获取名称的集合。

编辑:我刚刚学到一点关于自己的动态,我想也许你需要创建一个从继承自己的动态对象类DynamicObject 。 你会想在这个类的私人字典,然后覆盖到TrySetMemberTryGetMember

编辑旁白:我觉得一个强类型的视图模型的一个好处是,你可以接受它作为你的POST操作方法的参数。 MVC框架将处理模型绑定和操作方法简单,你有你的视图模型类的实例。 我不认为你有优势与动态,即使他们做的工作。

编辑结果:嗯,我尝试使用从DynamicObject派生的类,但是,当它试图渲染视图VS2010崩溃。 我没有得到任何异常,只是硬碰撞和Visual Studio重新启动。 下面的代码我想出了导致崩溃。

自定义动态类:

public class DynViewModel : DynamicObject
{
    private Dictionary<string, object> ViewDataBag;
    public DynViewModel()
    {
        this.ViewDataBag = new Dictionary<string, object>();
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        this.ViewDataBag[binder.Name] = value;
        return true;
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = this.ViewDataBag[binder.Name];
        return true;
    }
}

在控制器:

public ActionResult DynamicView()
{
    dynamic p = new DynamicViewModel.Models.DynViewModel();
    p.Name = "Test";
    p.Phone = "111-2222";

    return View(p);
}

我的看法是基本相同,是什么在问题中列出:

<p>Name: <%=Model.Name %></p>
<p>Phone: <%=Model.Phone %></p>

我的结论:这可能会实现,但在VS2010的Beta 1的我无法弄清楚,为什么我的代码导致Visual Studio崩溃。 我将在VS2010 Beta 2中再次尝试它,当它被释放,因为它是一个有趣的练习中学习动态。 然而,即使这是工作,我还没有看到过使用ViewData字典任何优势。

菲尔哈克来救援! 这里有一个博客帖子由菲尔哈克可能会帮助你。 它看起来像什么是你所期待的。 乐趣与方法缺失和C#4



Answer 3:

这里的实际误差( <>f__AnonymousType1.Name' is inaccessible due to its protection level )是使用匿名类型的结果。 匿名类型是隐式internal (至少在C#),因此它们只能被正常地从相同的组件访问。 因为你的观点被编译成在运行一个单独的程序 ,就不能访问internal匿名类型。

解决的办法是通过混凝土/班命名为榜样,以您的观点。 该视图本身仍然可以使用dynamic ,如果你想要的。



Answer 4:

上.NET 4.0匿名类型可以容易地转化为ExpandoObjects并且因此所有的问题是固定的转化本身的开销。 看看这里



文章来源: Dynamic typed ViewPage