动态类型ViewPage
这可能吗? 这就是我正在尝试的:
public ActionResult Index()
{
dynamic p = new { Name = "Test", Phone = "111-2222" };
return View(p);
}
然后我的视图继承自 System.Web.Mvc.ViewPage
并尝试打印出 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>
视图构造函数内置于框架中。
Is this possible? Here's what I'm trying:
public ActionResult Index()
{
dynamic p = new { Name = "Test", Phone = "111-2222" };
return View(p);
}
And then my view inherits from System.Web.Mvc.ViewPage<dynamic>
and tries to print out Model.Name.
I'm getting an error: '<>f__AnonymousType1.Name' is inaccessible due to its protection level
So basically, is what I'm trying to do just not possible? Why or why not?
Update: here's my view
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ...>
<%=Model.Name%>
<%=Model.Phone%>
</asp:Content>
The View constructor is built-in to the framework.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
方法不能返回匿名类型; 它们仅在定义它们的方法的范围内有效。
您应该使用之前定义的模型类并将其传递给您的视图。 传递未定义每个字段的 Model 类并没有什么问题。
更新:
我想我之前错了。 这应该有效。 也许问题出在视图内部。 您可以发布更多代码吗? 特别是视图及其构造函数。
更新第二个:
好吧,我错误地将匿名类型传递给另一个方法以用作动态变量 - 这是可以做到的。
但我也错误地相信你正在尝试做的事情会起作用。 对你来说不幸的是,它不会。 问题是您使用的是
ViewPage
,它在内部使用ViewDataDictionary
。 因为它们需要强类型,所以您将无法与它们一起使用动态对象。 内部结构只是内部不使用动态,并且在类型失败时指定动态。需要的是一个
DynamicViewPage
类和相应的DynamicViewDataDictionary
类,它们接受object
并将其在内部存储为动态。 然后您可以使用匿名类型并将其传递给您的视图。也就是说,你不会获得任何东西。 您将能够像您所做的那样指定视图(即
<%=Model.Name%>
),但您不会从强类型中受益。 就不会有智能感知,也不会有类型安全。 您也可以像 @Dennis Palmer 建议的那样使用非类型化的ViewDataDictionary
。这是一个有趣的(不幸的是,对我来说,很吸引人的)思想实验,但我认为,最终,它不会发生。 要么声明一个公共类型并将其传递给您的视图,要么使用非类型化字典。
Anonymous types cannot be returned by a method; they are only valid within the scope of the method in which they are defined.
You should use a Model class that you have previously defined and pass that to your View. There is nothing wrong with passing a Model class that does not have every field defined.
Update:
I think I was wrong before. This should work. Perhaps the problem is within the View. Can you post more code? Especially the View and its constructor.
Update the Second:
Ok, I was wrong about passing an anonymous type to another method for use as a dynamic variable -- that can be done.
But I was also wrong in my belief that what you're trying to do would work. Unfortunately for you, it will not. The problem is that you are using
ViewPage<TModel>
, which uses aViewDataDictionary<TModel>
internally. Because they require strong types, you won't be able to use dynamic objects with them. The internal structure just doesn't use dynamic internally, and specifying dynamic as the type fails.What would be needed is a
DynamicViewPage
class and correspondingDynamicViewDataDictionary
class that acceptobject
and store it internally as a dynamic. Then you could use an anonymous type and pass it to your Views.That said, you would not gain anything. You would be able to specify your Views as you have done (i.e.
<%=Model.Name%>
), but you would not benefit from strong typing. There would be no intellisense and there would be no type safety. You'd do just as well to use the untypedViewDataDictionary
as @Dennis Palmer suggests.This has been an interesting (and, unfortunately for me, absorbing) thought experiment, but I think, ultimately, that it's not going to happen. Either declare a public type and pass it to your Views, or use the untyped dictionary.
您希望通过使用动态类型获得什么好处?
使用 ViewData 字典是向视图输出添加任意对象/项目的非常简单的方法。
您不需要反射来获取视图中的属性名称。 只需使用 ViewData.Keys 即可获取名称集合。
编辑:我自己刚刚了解了一些关于动态的知识,我认为也许您需要创建自己的动态对象类,该类继承自 动态对象。 您需要在该类中拥有一个私有字典,然后重写
TrySetMember
和TryGetMember
。编辑旁白:我认为强类型 ViewModel 的一个优点是您可以接受它作为 POST Action 方法中的参数。 MVC 框架将处理模型绑定,并且在操作方法中您只需拥有 ViewModel 类的一个实例。 我认为即使它们确实有效,你也不会有这样的优势。
编辑结果:嗯,我尝试使用从DynamicObject派生的类,但是VS2010在尝试渲染视图时崩溃了。 我没有遇到任何异常,只是严重崩溃并且 Visual Studio 重新启动。 这是我想出的导致崩溃的代码。
自定义动态类:
在控制器中:
我的观点与问题中列出的基本相同:
我的结论:这可能有效,但在 VS2010 的 Beta 1 中我无法弄清楚为什么我的代码导致 Visual Studio 崩溃。 当 VS2010 Beta 2 发布时,我会再次尝试它,因为这是学习动力学的一个有趣的练习。 然而,即使这可行,我仍然没有看到比使用 ViewData 字典有任何优势。
菲尔·哈克 (Phil Haack) 来救援!这是菲尔·哈克 (Phil Haack) 撰写的博客文章,可能会对您有所帮助。 看起来这就是您要找的。 方法缺失和 C# 4 的乐趣
What benefit were you hoping to get from using the dynamic type here?
Using the ViewData dictionary is a very easy way of adding arbitrary objects/items to your view output.
You don't need reflection to get the property names within your View. Just use
ViewData.Keys
to get the collection of names.Edit: I've just learned a bit more about dynamics myself and I think maybe you need to create your own dynamic object class that inherits from DynamicObject. You'll want to have a private dictionary in that class and then override
TrySetMember
andTryGetMember
.Edit Aside: I think one advantage of a strongly typed ViewModel is that you can accept it as a parameter in your POST Action methods. The MVC framework will handle the model binding and in the action method you simply have an instance of your ViewModel class. I don't think you'll have that advantage with a dynamic even if they do work.
Edit Result: Well, I tried using a class derived from DynamicObject, but VS2010 crashes when it tries to render the view. I don't get any exception, just a hard crash and Visual Studio restarts. Here's the code I came up with that causes the crash.
The custom dynamic class:
In the controller:
My view is basically the same as what is listed in the question:
My Conclusion: This might work, but in the Beta 1 of VS2010 I can't figure out why my code causes Visual Studio to crash. I'll try it again in VS2010 Beta 2 when it is released because it is an interesting exercise in learning about dynamics. However, even if this were to work, I still don't see any advantage over using the ViewData dictionary.
Phil Haack to the rescue! Here's a blog post by Phil Haack that might help you out. It looks like it is what you were looking for. Fun With Method Missing and C# 4
这里的实际错误(
<>f__AnonymousType1.Name' 由于其保护级别而无法访问
)是使用匿名类型的结果。 匿名类型是隐式内部的(至少在 C# 中),因此只能从同一程序集中正常访问它们。 由于您的视图在运行时被编译成单独的程序集,因此它无法访问内部
匿名类型。解决方案是将具体/命名类作为模型传递到您的视图。 如果需要,视图本身仍然可以使用
dynamic
。The actual error here (
<>f__AnonymousType1.Name' is inaccessible due to its protection level
) is the result of using anonymous types. Anonymous types are implicitlyinternal
(at least in C#), therefore they can only be accessed normally from the same assembly. Since your view is compiled into a separate assembly at runtime, it can't access theinternal
anonymous type.The solution is to pass concrete/named classes as models to your view. The view itself can still use
dynamic
if you want.在 .NET 4.0 上,匿名类型可以轻松转换为 ExpandoObjects,因此所有问题都可以通过转换本身的开销来解决。
请查看此处
On .NET 4.0 Anonymous types can easily be converted to ExpandoObjects and thus all the problems is fixed with the overhead of the conversion itself.
Check out here